【问题标题】:Will it be possible to omit the type name when initializing C++2a class non-type template arguments?初始化 C++2a 类非类型模板参数时是否可以省略类型名称?
【发布时间】:2023-03-04 20:15:01
【问题描述】:

以下内容在 GCC 9.1 上无法编译(支持类非类型模板参数)

struct S { int i; };

template<S s>
struct T {};

int main()
{
    T<{0}> x{};
}

尽管模板参数s 是具体类型S,但编译器仍报告error: could not convert '{0}' from '&lt;brace-enclosed initializer list&gt;' to 'S'

T<S{0}> x{};

按预期工作,但 C++2a 是否允许省略具体类型名称 S,就像该语言的其他部分一样?

【问题讨论】:

  • 添加一个将 int 转换为 S 的隐式构造函数怎么样? ` constexpr S(int in) :i(in){}`
  • @Hui 这确实允许编译这个简单的示例,但我认为它不会与指定的初始化程序很好地交互,例如。话虽如此,在这种情况下,GCC 9.1 似乎确实允许指定的初始化程序,但是我认为它使用的是初始化程序列表,而不是做你期望的事情。也就是说,T 可以编译,但在将 .i 更改为任意标识符(例如 T)时也会编译。这是 GCC 错误吗?

标签: c++ c++20


【解决方案1】:

C++2a 是否允许省略具体类型名称 S?

[temp.arg.nontype]/2

非类型模板参数的模板参数应该是模板参数类型的转换常量表达式 ([expr.const])。

T&lt;{0}&gt; 中,{0} 不是S:它不是模板参数类型 (S) 的表达式。 {0} 将是 initializer list(在允许的情况下)。


奖金:

[dcl.init.list]/4

列表初始化可以发生在直接初始化或复制初始化上下文中;直接初始化上下文中的列表初始化称为直接列表初始化,复制初始化上下文中的列表初始化称为复制列表初始化。

模板参数不会发生初始化(除非发生,请参阅[temp.arg.nontype]/1)。

【讨论】:

  • 我的意思是肯定的,但为什么不直接说语法不允许大括号初始化列表作为模板参数:)
  • @Rak facepalm
  • 这是 CWG2450(尚未公开);目的是允许它,甚至可能在 C++20 模式下。 (定义模板参数对象初始化也会有问题,因为它对于类类型的对象来说很重要。)
  • 感谢@Davis 的更新。我会在本文档发布后立即更新我的答案。
猜你喜欢
  • 2021-02-18
  • 1970-01-01
  • 2019-09-23
  • 1970-01-01
  • 2011-10-07
  • 1970-01-01
  • 2019-11-15
相关资源
最近更新 更多