在C++的历次版本发布中,对C++模板参数的标准一直保持开放的态度,且对参数的要求也在逐渐放宽。从C++17开始,非类型的模板参数也可以在使用时定义了而不必定义在不同的作用域。
1 在模板中使用字符串
在模板编程中,非类型的模板参数被限制了诸多条件,只能从以下几种类型中获取,如:枚举、对象、指针、常量以及函数的左值引用、字符串变量。对于字符串变量,使用方式和之前的版本并没有太大的区别,都不能直接在模板类型参数中使用。如下面的代码:
template<const char *pMsg>
class ExecptionMsg{
//...
};
extern const char execptionMsg[] = "Hello"; // 外 部变量
const char execptionMsg_1[] = " World!"; // 内 部 变量
void foo()
{
ExecptionMsg<execptionMsg> msg; //编译成功
ExecptionMsg<execptionMsg_1> msg11; // 从C++11起编译成功
static const char execptionMsg_2[] = "Hello World!";
ExecptionMsg<execptionMsg_2> msg17; //C++17 编译成功
ExecptionMsg<"Hello"> msgError; //编译报错
}
如上代码所示,如果编译时没有注释:
ExecptionMsg<"Hello"> msgError;
编译将会报错,报错信息如下:
由此可见,在非类型的模板参数中,字符变量是不能直接使用的,在使用之前需要先进行定义。C++17除了继续遵守这个规范外,相对于之前的版本它允许在实例化模板的作用域内声明,然后使用。不得不说也算是一种进步了吧。
2 将指针作为模板实参
从C++11开始,已经允许将指针作为模板的实参,但是还有一个限制,既在模板实例化时不能将一个返回指针的函数当做模板的实参。但是从C++17开始,可以在模板中使用一个返回指针的函数当做实参,如下面的代码在C++17版本编译器中可以通过:
#include <iostream>
using namespace std;
template<int *pMsg>
class ExecptionMsg{
//...
};
int iValue=10;
constexpr int *getInt()
{
return &iValue;
}
int main()
{
static int num=10;
ExecptionMsg<&num> em;
ExecptionMsg<getInt()> emf;
return 0;
}
在C++14版本编译器中编译报错如下:
从报错信息可知,在C++17以前的版本中,使用指针作为模板的实参时需要对参数进行连接且不能将编译器内返回指针的函数在模板实例化时进行使用。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有