模板元编程
简要介绍
模板:
是C++提供的一种泛型编程工具,可以让函数和类在编译时根据类型参数进行实例化。
模板元编程:
核心思想是将计算推迟到编译时,利用模板递归、特化和偏特化等机制,进行类型推导、编译期计算和代码生成。这样可以减少运行时开销。
基本技巧:
类型特化:根据不同类型提供不同的实现
递归模板:通过模板的递归实例化,在编译期进行计算
std::integral_constant:用于封装常量值,以便在编译时作为类型传递
基本例子
计算阶乘:
通过模板递归,可以在编译期间计算出一个数的阶乘
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #include <iostream> template <int N>struct Factorial { static const int value = N * Factorial<N - 1 >::value; };template <>struct Factorial <0 > { static const int value = 1 ; };int main () { std::cout << "Factorial of 5 is: " << Factorial<5 >::value << std::endl; return 0 ; }
编译时常量表达式:
std::integral_constant是C++11引入的一个模板类,用于封装常量值,可以在编译时传递常量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #include <iostream> #include <type_traits> template <typename T>void printType (T value) { if (std::is_integral<T>::value) { std::cout << "Integral type: " << value << std::endl; } else { std::cout << "Non-integral type: " << value << std::endl; } }int main () { printType (42 ); printType (3.14 ); return 0 ; }
类型选择:
std::conditional是C++11引入的一个模板类,它根据条件选择两种类型中的一种
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #include <iostream> #include <type_traits> template <typename T>void printType (T value) { using Type = typename std::conditional<std::is_integral<T>::value, int , double >::type; Type result = static_cast <Type>(value); std::cout << "Result: " << result << std::endl; }int main () { printType (42 ); printType (3.14 ); return 0 ; }
模板特化:
指的是对某个特定类型或特定类型组合提供模板的定制实现。
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #include <iostream> using namespace std;template <typename T>void func (T t) { cout << "Generic template: " << t << endl; }template <>void func <int >(int t) { cout << "Specialized template for int: " << t << endl; }int main () { func (10 ); func (3.14 ); }
模板偏特化:
通常用于处理模板参数中的某些类型特征(比如说指针类型、数组类型等)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include <iostrea> using namespace std;template <typename T>void func (T t) { cout << "Generic template: " << t << endl; }template <typename T>void func (T* t) { cout << "Template specialized for pointer type: " << *t << endl; }int main () { int a = 10 ; int * p = &a; func (a); func (p); }
函数重载与模板特化/偏特化的区别:
函数重载:指的是为同一个函数名提供多个不同参数列表的实现。编译器根据传入参数的类型来选择合适的重载版本。函数重载是基于函数参数的类型和数量来选择执行哪个函数,而不涉及模板概念
模板特化/偏特化:是针对模板的类型参数进行定制,根据传入的类型来选择对应的模板实例化。
其他
常用的模板元编程技巧:
类型列表(Type List):一种用于存储多个类型的容器
SFINAE(Substitution Failure Is Not An
Error):一种技巧,通过使模板在不适用时失败,从而为某些类型提供特化版本
元编程工具:
std::enable_if:条件启用模板功能的一种方法
std::is_same:判断两个类型是否相同
std::tuple:一个可以容纳多个不同类型的容器,类似于vector,但每个元素可以是不同的类型
std::index_sequence:生成从0到N的整数序列,通常用于编写递归和展开参数包