Class类型非类型模板参数初始化不编译

Class type non-type template parameter initialization does not compile

我的印象是以下内容应该成为新 C++20 标准下的有效代码:

struct Foo
{
  int a, b;
};

template<Foo>
struct Bar
{};

Bar<{.a=1, .b=2}> bar;

然而,gcc 10.2.0 设置了 -std=c++20 时会抱怨:could not convert ‘{1, 2}’ from ‘<brace-enclosed initializer list>’ to ‘Foo’ 并且 Clang 也无法编译此代码段。有人可以指出为什么格式不正确吗?

这个template-argument

{.a=1, .b=2}
根据 template-argument 的语法,

是不允许的,它只允许以下结构:

template-argument:

constant-expression

type-id

id-expression

A brace-init 列表不是上述任何构造,它实际上是一个 initializer,因此不能用作 template-argument.

您可以明确说明用作 template-argument:

的对象的类型
Bar<Foo{.a=1, .b=2}> bar;

这会起作用,因为这是 constant-expression。

这是一个 C++ 语法问题。用于模板参数的东西必须是 either type-ids, id-names, or constant-expressions.

并且 braced-init-list 不是任何类型的表达式。它们只能在语法上出现在少数地方,特别是那些用于初始化对象或变量的地方。

在过去,它并不真正相关,因为没有太多理由使用 braced-init-list 来初始化少数有效的 NTTP。显然这已经改变了,所以这是一种疏忽。但这是 C++20 标准所说的。