C++20标准对使用子对象作为模板非类型参数有什么看法?
文章“模板参数和模板参数”的“模板非类型参数”段落指出:
唯一的例外是类类型的非类型模板参数及其子对象(C++20 起)中引用或指针类型的非类型模板参数和引用或指针类型的非静态数据成员不能引用/是地址
- 一个临时对象(包括在引用初始化期间创建的对象);
- 字符串文字;
- 的结果
typeid;- 预定义变量
__func__;- 或上述 (C++20 起)之一的子对象(包括非静态类成员、基子对象或数组元素)。
重点是我的。
下面是一个例子
template<int* p> class X {};
int a[10];
struct S
{
int m;
static int s;
} s;
X<&a[2]> x3; // error: address of array element
X<&s.m> x4; // error: address of non-static member
X<&s.s> x5; // ok: address of static member
X<&S::s> x6; // ok: address of static member
根据引用的语句,error注释中带有单词的行应该可以被支持 c++20 的 c++ 编译器编译,因为a[2]ands.m既不是临时对象也不是字符串文字,typeid也不是预定义变量的结果,也不__func__是上述之一的子对象。事实上,gcc 11.1 编译代码没有错误,但是clang 12.0.0 编译代码有错误。
此外,N4835 草案在第 13.4.2 段中声明了以下内容
非类型模板参数的模板参数应是模板参数类型的转换常量表达式 (7.7)。对于引用或指针类型的非类型模板参数,或者对于类类型或其子对象的非类型模板参数中的每个引用或指针类型的非静态数据成员,引用或指针值不得引用到或成为(分别)的地址:
- 一个子对象(6.7.2),
- 一个临时对象(6.7.7),
- 字符串文字 (5.13.5),—(2.4)
typeid表达式的结果(7.6.1.7),或- 预定义
__func__变量 (9.5.1)。
并包含上述示例。再次强调是我的。
考虑到这个草案,clang 可以正常工作而 gcc 不能,因为a[2]和s.m是子对象。
深层发掘。该N4878草案中包含段落13.4.3以下文本
对于引用或指针类型的非类型模板参数,或者对于类类型或其子对象的非类型模板参数中的每个引用或指针类型的非静态数据成员,引用或指针值不得引用到或成为(分别)的地址:
- 一个临时对象(6.7.7),
- 字符串文字对象(5.13.5),
typeid表达式的结果(7.6.1.8),- 预定义
__func__变量(9.5.1),或- 以上之一的子对象(6.7.2)。
并且不包含示例。
本主题开头引用的文本对应于 N4878 草案,因此 gcc 可以正常工作,而 clang 则不能。
什么是C ++ 20约subojects为模板非类型参数的使用标准的发言权?哪个编译器确实符合标准?