为何C++17允许将数组首元素地址作为模板非类型实参?
数组元素地址作为非类型模板实参的C++版本差异解析
先看这段代码:
template<typename T, T nontype_param> class C {}; int a[10]; C<int *, &a[0]> err3;
这段代码在C17之前的标准下会编译报错,但在C17及之后可以正常通过编译,原因如下:
在C++17之前的标准中,指针类型的非类型模板参数不能指向对象的子对象(比如数组的元素),即使该对象拥有静态存储期。而&a[0]是全局数组a的首元素地址,属于对象的子对象,因此不符合当时的规则,会触发编译错误。
到了C++17,标准放宽了这一限制:只要指针指向的是具有静态存储期的对象,哪怕这个指针指向的是该对象的子对象(比如数组元素),也允许作为指针类型的非类型模板实参。这里的全局数组a显然满足静态存储期要求,所以&a[0]可以合法地作为模板实参。
你提到的规则说明里,关于“数组元素作为禁止的子对象”是C20才明确纳入的限制,这一规则并不适用于C17。C17的规则中并没有禁止指向静态存储期数组元素的指针作为非类型模板实参,所以这段代码在C17下能正常编译。
唯一的例外是,引用或指针类型的非类型模板参数,以及类类型非类型模板参数及其子对象(C20起)中引用或指针类型的非静态数据成员,不能引用/是以下对象的地址:
或是上述对象的子对象(包括非静态类成员、基类子对象或数组元素,C20起)。
内容的提问来源于stack exchange,提问作者fade
相关产品推荐
相关产品推荐

