C++中的模板超程式設計
概述
模板超程式設計可以說是C++中最困難也是最強大的程式設計正規化。模版超程式設計不同於普通的執行期程式,它執行完全是在編譯期,並且它操縱的資料不能是執行時變數,只能是編譯期常量(且不可修改)。因此,模版超程式設計需要很多技巧,在這裡你會遇到非常多的列舉常量、繼承、模板偏特化、可變模板引數、型別萃取等方法,如果要讀懂STL庫,那麼模板超程式設計必須要掌握;不僅如此,C++中的許多黑科技都是依賴於模板超程式設計的,例如我們甚至可以寫出編譯期排序的演算法
模板超程式設計:template meta programing
前置知識
模板超程式設計又兩個部分組成:元資料和元函式。元資料是指編譯期能在編譯期處理的資料,即編譯期常量;元函式指操縱元資料的函式,在編譯期呼叫,它通常表現為一個模板類或一個模板函式
模板超程式設計十分特殊,它無法使用if-else
,for
,while
這些執行期語句,在模板超程式設計中,我們時常會使用到這些語法:
enum
,static-constexpr:用來定義編譯期的整數常量using
,typedef
:定義元資料- T,Ts...:用來宣告元資料型別
template
:定義元函式::
:用來解析型別作用域獲取元資料
constexpr
type_traits
<type_traits>
是C++11提供的模板元基礎庫,它提供了模板超程式設計中需要的常用的基礎元函式
std::integral_constant,定義編譯期常量
舉個例子,C++11中提供了std::integral_constant
來定義編譯期常量
template<typename T> using one_constant = std::integral_constant<T, 1>; template<typename T> struct one_struct : std::integral_constant<T, 1> {};
因此我們可以使用one_constant<int>::value
或one_struct<int>::value
來獲取編譯期常量int 1
而在C++11之前,我們定義這個常量就需要用到enum
或static-const
struct one_struct
{
enum { value = 1 };
};
struct one_struct
{
static const int value = 1;
};
然後通過one_struct::value
來訪問值,其中enum
能隱式轉換為int
std::integral_constant
的實現也非常的簡單
template <class _Ty, _Ty _Val>
struct integral_constant {
static constexpr _Ty value = _Val;
using value_type = _Ty;
using type = integral_constant;
constexpr operator value_type() const noexcept {
return value;
}
_NODISCARD constexpr value_type operator()() const noexcept {
return value;
}
};
可以看到,通過C++11的<type_traits>
提供的一個簡單的std::integral_constant
就可以很方便的定義編譯期常量,而無需再去使用enum
和static-const。緊接著,庫中又提供了編譯期常量的bool
型別
using true_type = bool_constant<true>;
using false_type = bool_constant<false>;
std::integer_sequence,定義編譯期整數序列
為什麼說是整形呢,請看原始碼
// 一個型別加上一個非型別模板引數包
template <class _Ty, _Ty... _Vals>
struct integer_sequence { // sequence of integer parameters
static_assert(is_integral_v<_Ty>, "integer_sequence<T, I...> requires T to be an integral type.");
using value_type = _Ty;
_NODISCARD static constexpr size_t size() noexcept {
return sizeof...(_Vals);
}
};