C++模板元编程
为什么需要模板函数?
- 避免重复写代码
模板函数定义
- 使用
template <class T>
或者template <typename T>
- 其中T是可以变成任何类型
- 调用时候T会替换成需要的类型
twice<int>
会将T替换成int
template <class T>
T twice(T t)
{
return T * 2;
}
int main()
{
std::cout << twice<int>(2) << std::endl;
}
除此之外,C++规定,当模板类型参数T作为函数参数时,可以省略该模板参数。自动根据调用者的参数去判断类型
模板参数默认类型
如果模板参数返回了T类型,且没有出现再参数中,那么编译器无法推断T的类型,这个时候我们不得不指定类型。但是,我们也可以通过template <class T = int>
这种方式表示T的默认类型是int
template <class T = int>
T two()
{
return 2;
}
int main()
{
std::cout << two(2) << std::endl;
}
-
除了上面的以
class T
作为参数类型以外,我们还可以用template <int N>
来声明一个整数N作为模板参数 -
不过模板参数只支持整数类型(包括enum),浮点类型、指针类型不能声明为模板参数,自定义类型也不可以
模板参数:多个模板参数
int N
和 class T
可以一起使用,你只需要指定其中一部分参数即可,会自动根据参数类型(T msg)、默认值(int N = 1),推断尖括号里没有指定的那些参数
template <int N = 1, class T>
void two(T msg)
{
for (int i = 0; i < N; i++)
{
std::cout << msg << std::endl;
}
}
int main()
{
two("one");
}
模板的惰性:延迟编译
要证明模板的惰性,只要下面的例子
template <class T = void>
T two()
{
"aaa" = "aaa";
}
int main()
{
std::cout << "aa" << std::endl;
}
只要是编译器编译了two
函数,则一定会报错,但是实际编译的时候是可以编译的,这是因为模板没有被调用,如果模板被调用了,才会编译报错。
总结
-
类型作为参数:
template <class T>
-
整形作为参数:
template <int N>
-
定义默认参数:
template <int N = 0, class T = int>
-
使用模板函数:
myfunc<T, N>()
-
模板函数可以自动推导类型,从而参与重载
-
模板具有惰性,多次编译的特点