C++ Templates
auto
类型推导会忽略掉引用和CV限制符(const
、voliate
等)
1 2 3 |
|
-
std::decltype
推导出来的类型会包含CV限制符和引用,通过std::decay
可以去掉这些CV限制符和引用 -
std::common_type
可以得到多个类型的common type
可以通过std::decltype
结合?
号操作符实现std::common_type
的效果
1 2 3 4 5 |
|
但是存在一个问题就是T1和T2需要有构造含糊
Two-Phase Translation
- 模版定义时检查(不检查和模版参数相关的)
- 语法错误
- 使用了未知的类型、函数名、变量名等
-
静态断言
-
模版实例化(和模版参数相关的都要检查)
- 所有依赖模版参数的地方都会进行检查
examples:
1 2 3 4 5 6 7 8 9 10 |
|
the type trait std::decay<> is used, which returns the resulting type in a member type the C++ standard library provides a means to specify choosing “the more general type.” std::common_type<>::type yields the “common type” of two (or more) different types passed as template arguments.
函数模版、和普通函数可以共同构成函数重载,决策的时候,普通函数有限匹配。除非函数模版可以实例化出最佳匹配。 XXX<> 模版的参数可以是空,表明强制使用函数模版,其模版类型通过参数来推导。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
显示初始化的模版,其定义可以不用放在头文件中
1 2 3 4 5 6 7 |
|
函数模版不能部分特化,只能全特化
FAQ
- 传值还是传引用?
通常意义来说,传引用要比传值效率要高,可以避免不必要的内存拷贝。然后传值通常会更好,出于以下几个原因:
- 语法更简单
- 编译时优化更好
- 移动语义通常比拷贝更好
- 某些情况是没有拷贝和移动的
此外对于模版来说,还有另外一些原因:
- 一个模版可以适配简单类型和负责类型,因此选择适合负责类型的传参方式,对于简单类型来说反而适得其反
- 作为调用者可以仍然可以可以通过
std::ref
和std::cref
自主选择是传值还是传引用 -
传递常量字符串会成为大问题,但是通过引用来传递被认为会造成更大的问题
-
为什么不
inline
?
通常来说函数模版不需要声明为inline,因为我们可以定义noinline的函数模版在一个头文件中,然后可以在多个编译单元中包含这个头文件。 inline本身的目的就是在多个地方进行展开,避免函数调用的进栈和入栈的开销,但是对于全特化的模版来说不适用这个规则。
- 为什么不
constexpr
?
TODO