别名模版和变量模版

来源:互联网 发布:mac查看电池循环 编辑:程序博客网 时间:2024/05/16 06:15

点击打开链接

两种模板(C++03) -> 四种模板(C++14)

传统C++只有两种模板,分别是类模板和函数模板。而最新的C++标准中总共有四种模板,这是因为C++11引入了别名模板,而C++14则引入了变量模板。

别名模板(alias template)

别名模板:带模板参数的类型别名
类型别名(type alias)是C++11新引入的语法形式:
using newtype = oldtype;
在语法功能上,它相当于传统C/C++语言中的typedef语句:
typedef oldtype newtype;
可以看出,类型别名中原有类型和别名的定义顺序与typedef语句正好相反。除此之外,类型别名与typedef语句还有一点不同,类型别名可以加上模板参数形成别名模板:
template<typename ...> using newtype = oldtype<...>;
注:C++11引入类型别名意图取代typedef语句的原因在于:无法直接在typedef语句的基础上直接构建别名模板。这是因为typedef语句自身存在某些局限性,直接给typedef加上模板参数会带来语法解析上的问题。

[cpp] view plain copy
  1. template<typename T, typename U>  
  2. struct A;  
  3.   
  4. template<typename T>  
  5. struct B  
  6. {  
  7.     typedef A<T, int> type;  
  8. };  
  9.   
  10. template<typename T>  
  11. using C = A<T, int>;  
  12.   
  13. template<typename T>  
  14. using D = typename B<T>::type;  
代码说明:
  • 假设我们有一个带两个模板参数T和U的类模板A。现在我们需要声明一个只带一个模板参数T的类模板,使其等价于模板参数U为int类型的A模板。也就是说,我们需要一个模板参数T任意,模板参数U为int类型的A模板的别名,或者说A<T, int>的别名。
  • 在C++11之前,答案为类模板B。要定义类型别名,必然要使用typedef。但由于typedef不能带模板参数,所以typedef必须被嵌入到一个带模板参数的类模板里面。在模板参数为T的类模板B里面,类型type被定义成A<T, int>的别名。也就是说typename B<T>::type被定义成了A<T, int>的别名。
  • 在C++11之后,答案为别名模板C。类型别名直接就可以带模板参数。C<T>直接被定义成了A<T, int>的别名。
  • 如果出于某种原因,在定义别名的时候无法使用类模板A而只能使用类模板B,别名模板也能发挥作用。这里D<T>直接被定义成了typename B<T>::type的别名。由于后者是A<T, int>的别名,所以D<T>其实也是A<T, int>的别名。
  • 这段代码展示了别名模板的主要用途:1.为部分模板参数固定的类模板提供别名。2.为类模板中嵌入的类型定义提供别名。

变量模板(variable template)

变量模板:变量的家族
变量模板是C++14新引入的模板形式,在语法功能上它相当于一个没有参数但是有返回值的函数模板,相对于后者,变量模板在语法上更清晰,更能反映编程者的意图。
template<typename ...> type variable;

[cpp] view plain copy
  1. #include <iostream>  
  2. #include <iomanip>  
  3. using namespace std;  
  4. // 函数模板  
  5. template<class T>  
  6. constexpr T pi_fn()  
  7. {  
  8.     return T(3.1415926535897932385);  
  9. }  
  10. // 变量模板  
  11. template<class T>  
  12. constexpr T pi = T(3.1415926535897932385);  
  13.   
  14. int main()  
  15. {  
  16.    cout << pi_fn<int>() << pi<int> << '\n'// 33  
  17.    cout << setprecision(10) << pi<float> << '\n'// 3.141592741  
  18.    cout << setprecision(10) << pi<double> << '\n'// 3.141592654  
  19. }  
代码说明:
  • 这段代码所展示的是变量模板的经典用例:圆周率pi。
  • 假设我们需要一个能转成一定数值类型的圆周率。
    如果数值类型为int,圆周率pi就是int(pi)=3。
    如果数值类型为float,圆周率pi就是float(pi)=3.1415927。
    如果数值类型为double,圆周率pi就是double(pi)=3.141592653589793。
  • 在C++14之前,这样的常量只能被定义为函数模板。
  • 在C++14之后,我们可以用变量模板直接定义这样的常量。

原创粉丝点击