【问题标题】:What does the C++20 standard say about usage of subojects as template non-type arguments?C++20 标准对使用子对象作为模板非类型参数有什么看法?
【发布时间】:2021-12-20 07:59:59
【问题描述】:

文章“模板参数和模板参数”的“Template non-type arguments”段落指出:

唯一的例外是非类型模板参数的引用 或指针类型和引用或指针的非静态数据成员 键入类类型及其子对象的非类型模板参数 (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

根据引用的语句,在 cmets 中带有单词 error 的行应该可以被支持 c++20 的 c++ 编译器编译,因为 a[2]s.m 既不是临时对象,也不是字符串文字,也不是typeid 也不是预定义的变量 __func__ 也不是上述之一的子对象。其实gcc 11.1编译code没有错误,但是clang 12.0.0编译code有错误。

此外,draft 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 是子对象。

深入挖掘。 draft 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 标准对将子对象用作模板非类型参数有何规定?哪个编译器符合标准?

【问题讨论】:

标签: c++ language-lawyer c++20


【解决方案1】:

措辞作为P1907R1 的一部分进行了更改,后者被作为C++20 的一部分采用。请注意,您引用的初稿 - N4835 - 早于本次采用(该草案于 2019 年 10 月发布,本论文于次月在 2019 年 11 月的贝尔法斯特会议上通过)。最接近 C++20 的草案是 N4861,您也可以在 html form 中方便地查看。

结果如下:

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]s.m 都不是以下任何项的子对象:临时、字符串文字、typeid 表达式的结果或 __func__


cppreference 示例已经更新以反映这一点,现在 cmets 读取:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-07
    • 2012-08-13
    • 1970-01-01
    • 2018-08-24
    • 2020-05-02
    • 1970-01-01
    相关资源
    最近更新 更多