类型退化 std::decay
template<class T>
struct decay;
- 若
T
是类型U的数组
/对类型U的数组的引用
, 则退化后的类型为U*
- 若
T
为一个函数类型F/对函数的引用, 则退化后的类型为std::add_pointer<F>::type
- 否则, 对其余所有类型, 其退化后的类型为
std::remove_cv<std::remove_reference<T>::type>::type
因此粗略来讲, decay
将数组/函数类型退化为指针, 将其余的类型去除引用和const
&volatile
修饰符.
辅助类 decay_t<T>
, 用于取出退化后的类型
template <class T>
using decay_t = typename decay<T>::type; // cpp14
可能的实现
- 先去除T的引用, 得到类型U
- 若U是数组类型, 则去掉数组的修饰后的得到 变量类型V, V*就是退化类型
- 若U是函数类型, 则用 add_pointer 转为指针类型.
- 否则, 用remove_cv去除其可能的const/volatile修饰符.
转为指针类型 add_pointer
辅助类 add_pointer_t<T>
template <class T>
using add_pointer_t = typename add_pointer<T>::type ;
若T是引用类型, 则结果为指向其引用类型的指针. int& ==> int*
若T是个对象类型 或 无引用/cv 修饰的函数类型 或 void类型, 则返回T*
若T是个CV修饰/引用修饰的函数类型, 则只返回T
返回数组类型中的元素类型 std::remove_extent
std::extent
在cpp中指代的是数组定义中维度的部分(即数组长度 [N]
)
用法 : std::extent<数组类型, 第N维 = 0>::value
std::extent<int[3][4]>::value ⇒ 3
std::extent<int[3][4], 1>::value ⇒ 4
因此std::remove_extent
就是返回数组定义中关于元素类型的部分: int[3][4] ---> int
参数包 Parameter pack
一个模板parameter pack
是一个能接收0或多个模板实参(非类型实参/类型实参/模板)的 模板形参
一个函数parameter-pack
是一个能接收0或多个函数实参的 函数形参
一个含有至少一个parameter-pack
的模板被称为可变参数模板
语法
模板parameter-pack
用于 模板别名, 类模板, 变量模板, 函数模板的参数列表中
typename... 参数包名
template<参数列表> typename ... 参数包名 // C++17以后
函数parameter-pack
声明中: 用在变参函数模板的函数参数列表中:
Ts… some_args
parameter-pack的展开
适用于在某个可变模板的定义中.
扩展为由逗号分割的含0或多个pattern的列表
eg : &args …
非类型的模板parameter-pack
类型模板parameter-pack
一个模板类型的模板parameter-pack
一个函数parameter-pack