C++11中type_traits中的基石
C++標準庫的的編寫方法是基於模板元來程式設計的,既然是用模板,那麼就少不了與型別打交道,而C++11標準庫中新加入了<type_traits>
標頭檔案,這個裡面新加入了很多與型別特性有關的模板元,在編譯期間這些東西就是利器,非常好用。
而開啟<type_traits>
標頭檔案,看到的第一個模板類就是integral_constant
,這個類是type_traits
的基石,基本上type_traits
都直接或間接繼承自integral_constant
,而且,C++標準庫中還有很多模板類也是繼承了integral_constant
,例如std::ratio
。
integral_constant
先來看看原始碼:
/// integral_constant
template<typename _Tp, _Tp __v>
struct integral_constant
{
static constexpr _Tp value = __v;
typedef _Tp value_type;
typedef integral_constant<_Tp, __v> type;
constexpr operator value_type() const
{
return value;
}
#if __cplusplus > 201103L
#define __cpp_lib_integral_constant_callable 201304
constexpr value_type operator()() const
{
return value;
}
#endif
};
template<typename _Tp, _Tp __v>
constexpr _Tp integral_constant< _Tp, __v>::value;
可以看到,integral_constant
只有一個靜態常量表達式變數value
,由於是靜態變數,因此要在類外宣告;
然後就是兩個typedef
,這是traits
的老套路了,喜歡在類中重定義一些型別,說白了就是把別人東西的包一層,然後作為一箇中間層告訴使用者需要的東西;
接著就是兩個操作符過載了。
在C++14中過載了函式運算子,這非常有用,假設現在你需要寫一個函式,這個函式返回App的版本號,這個版本號是個常量,不會變(假設啊),你肯定會這麼寫:
#define APP_VERSION 20181010L
const char * GetAppVersion() { return APP_VERSION; }
那麼在C++14中,你可以這麼寫:
struct GetAppVersion : public std::integral_constant<unsigned int, APP_VERSION> {};
然後像函式一樣呼叫就行了,auto appVersionString = GetAppVersion()
,非常好用。因此,凡是需要返回一些常量的函式都可以這麼寫。
到這裡,原始碼就分析完了,是不是特別簡單,但是,這東西有什麼用呢?貌似還沒有說清楚。
先來看看三個特別重要的東西:
/// The type used as a compile-time boolean with true value.
typedef integral_constant<bool, true> true_type;
/// The type used as a compile-time boolean with false value.
typedef integral_constant<bool, false> false_type;
template<bool __v>
using __bool_constant = integral_constant<bool, __v>;
前兩個是不是好熟悉啊,看《STL原始碼剖析》,SGI有一個__type_traits
也有__true_type
和__false_type
,從前面的兩條下劃線可以知道,當時的__type_traits
只能供內部使用,並不是C++標準規範之中的內容,然後再來看看當時的這兩個型別是如何定義的:
struct __true_type {};
struct __false_type {};
把這兩個定義和C++11中的兩個定義比較一下,你就會發現,C++11的true_type / false_type
是多麼有血有肉,呼叫std::true_type::value
還可以得到true
。
這也是為什麼我之前說type_traits
中的大部分類都直接或間接繼承自integral_constant
,你可以繼續看看type_traits
中其他類,凡是帶字首is_*
的類的偏特化或特化都是繼承自true_type
。例如下面的__is_pointer_helper
:
template<typename>
struct __is_pointer_helper : public false_type { };
template<typename _Tp>
struct __is_pointer_helper<_Tp*> : public true_type { };
這種例子在type_traits
中比比皆是。
__bool_constant
這是一個輔助型別重定義,可以用在模板函式過載中。
integral_constant
的另一作用就是用在std::ratio
編譯器分數類中,這個在另一篇部落格會有介紹。
目前解除到的關於integral_constant
就這麼多,以後有機會再完善。