C++14尝鲜:别名模板和变量模板

两种模板(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 using newtype = oldtype<...>;
注:C++11引入类型别名意图取代typedef语句的原因在于:无法直接在typedef语句的基础上直接构建别名模板。这是因为typedef语句自身存在某些局限性,直接给typedef加上模板参数会带来语法解析上的问题。

template
struct A;

template
struct B
{
    typedef A type;
};

template
using C = A;

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

变量模板(variable template)

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

#include 
#include 
using namespace std;
// 函数模板
template
constexpr T pi_fn()
{
    return T(3.1415926535897932385);
}
// 变量模板
template
constexpr T pi = T(3.1415926535897932385);

int main()
{
   cout << pi_fn() << pi << '\n'; // 33
   cout << setprecision(10) << pi << '\n'; // 3.141592741
   cout << setprecision(10) << pi << '\n'; // 3.141592654
}
代码说明:
  • 这段代码所展示的是变量模板的经典用例:圆周率pi。
  • 假设我们需要一个能转成一定数值类型的圆周率。
    如果数值类型为int,圆周率pi就是int(pi)=3。
    如果数值类型为float,圆周率pi就是float(pi)=3.1415927。
    如果数值类型为double,圆周率pi就是double(pi)=3.141592653589793。
  • 在C++14之前,这样的常量只能被定义为函数模板。
  • 在C++14之后,我们可以用变量模板直接定义这样的常量。

你可能感兴趣的:(C++)