编译时常量语语法是static const [[integer type]]name=value
编译时常量可以是:
1.整型字面值,如27,0x05
2.sizeof和具有整型结果的非标准语言运算符,如__alignof__
3.非类型模板参数
template<int N>
class AnotherClass{
SomeClass<N>myMember;//这里的N就是
};
4.整型静态常量
5.一些宏,如__LINE__
一个参数可以依赖前面的参数:
template<class T,T value>class Y{}:
类的模板成员函数:
struct mathematics{
template<class scalar_t>
scalar_t sq(scalar_t x)const{return x*x;}
};
类模板的模板成员函数:
template<classscalar_t>
structmore_mathematics
{
template<classother_t>
static scalar_tproduct(scalar_t x,other_t y)
{return x*y}
};
当编译器不清楚标识符是一个类型名时,使用typename,比如:
template<typename T>
struct MyClass
{
typedef double Y;
typedef T Type;
};
template <>
struct MyClass<int>
{
static const int Y = 314;
typedef int Type;
};
int Q = 8;
template<typename T>
void SomeFunc()
{
MyClass<T>::Y* Q;
};
如果Y是一个int变量,那么Y*Q表示314*8,如果Y是一个类型,那么Q是一个指向Y类型的指针。
任何间接或直接依赖于未知模板参数的名称是依赖名称,Y是一个依赖名称,因为它的意义依赖于T,T是一个未知参数。如果依赖名称是一个类型,那么它必须使用typename。
在处理两个同类型的对象时,不调用模板构造函数和模板赋值操作符。
函数类型是一种类型,函数指针是一个指针。但是函数类型无法被构造。
引用可以阻止函数指针的退化。
类模板的模板成员名称前要加一个template:
template<typename X>
struct outer
{
template <typename T>
static T g(T x)
{
return x+1;
}
};
template<typename X>
void do_it()
{
FUNC_T f1 = outer<X>::template g<double>;//因为依赖于X
}
对于内部模板类,typaname和template都要加上。
template<typename X>
struct outer
{
template <typename T>
struct inner {};
};
template<typename X>
void do_it()
{
typename outer<X>::template inner<double>I;
}
如果一个类模板中有成员不依赖于它的模板参数,可以将成员转为类然后继承它们。
模板声明放在h文件,实现放在cpp文件,并且在cpp中显式实例化模板:
template class X<double>;
template double sq<double>(constdouble&);
那么就可以只发布头文件和二进制文件,算法实现保密。
extern,跳过实例化,从其他地方借用模板体。
重载和函数模板参加解析,特化不参加解析。如果重载解析选择了函数模板,才在函数模板和特化之间进行选择。
不同的模板可以重载。书写特化时要显式地指出参数。
只有在命名空间级别,模板的特化才是合法的。
实参推导只针对函数模板,类模板没有实参推导。
一个模板名称(例如std::vector)和它产生的类名称(例如std::vector<int>)不同。在类级别,它们等价
在模板中,模板名代表一个模板。
类模板可以全部特化或部分特化。
部分特化可以递归。
推导是通过模式匹配完成的,编译器不需要执行任何类型的代数运算。
如果一个类型被包含在类模板中,那么外部类的参数不能推导出来。
解决方法1.为外部类添加一个参数
解决方法2:显式指定外部类的参数
类模板特化可能与通用模板完全无关,它们不需要有相同的成员,并且成员函数可以有不同的签名。
内部类模板有自己的参数集合,并且知道外部类的所有参数。
SCARY初始化(seemingly erroneous(constrained by conflictingtemplate parameters), but actually work with the right implementation)两个应该不同的内部类(outer<T1>::inner和outer<T2>::inner)实际上共享实现。