The "模板非类型参数”文章“模板参数和模板参数”的段落指出:
唯一的例外是引用的非类型模板参数
或指针类型以及引用或指针的非静态数据成员
输入类类型及其子对象的非类型模板参数
(C++20 起) 不能引用/成为以下地址
- 临时对象(包括在引用初始化期间创建的临时对象);
- 字符串文字;
- 的结果
typeid
;
- 预定义变量
__func__
;
- or a 子对象(包括非静态类成员、基子对象或数组元素)上述之一 (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]
and s.m
既不是临时对象,也不是字符串文字,也不是typeid
也不是预定义变量__func__
也不是上述之一的子对象。事实上,gcc 11.1 编译了code没有错误,但是 clang 12.0.0 编译了code有错误。
此外,草案 N4835在第 13.4.2 段中声明以下内容
非类型模板参数的模板参数应转换为
模板参数类型的常量表达式 (7.7)。为一个
引用或指针类型的非类型模板参数,或者对于每个
引用或指针类型的非静态数据成员
类类型或其子对象的非类型模板参数,
引用或指针值不得引用或成为以下地址
(分别):
- a 子对象(6.7.2),
- 临时对象(6.7.7),
- 字符串文字 (5.13.5),—(2.4)a 的结果
typeid
表达式(7.6.1.7),或
- 一个预定义的
__func__
变量(9.5.1)。
并包含提到的示例。再次强调是我的。
考虑到这个草案,clang 可以正常工作,而 gcc 则不能,因为a[2]
and 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关于使用主题作为模板非类型参数的标准说法?哪个编译器符合标准?
措辞发生了变化,作为P1907R1,它被采纳为 C++20 的一部分。请注意,您引用的初稿 -N4835- 早于本次通过(该草案于 2019 年 10 月发布,本文于次月在 2019 年 11 月的贝尔法斯特会议上通过)。最接近 C++20 的草案是N4861,您也可以方便地在其中查看html表格.
结果如下:
template<int* p> class X {};
int a[10];
struct S
{
int m;
static int s;
} s;
X<&a[2]> x3;
X<&s.m> x4;
是一个有效的 C++20 程序,因为两者都不是a[2]
nor s.m
是以下任一对象的子对象:临时对象、字符串文字、a 的结果typeid
表达式,或__func__
.
cppreference 示例已更新以反映这一点,其中注释现在如下:
X<&a[2]> x3; // error (until C++20): address of array element
X<&s.m> x4; // error (until C++20): address of non-static member
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)