聚合类和不可行的构造函数模板

Igo*_* R. 2 c++ language-lawyer aggregate-initialization c++20

众所周知,在 C++20 中,具有用户声明的构造函数的类不是聚合的。

现在,考虑以下代码:

#include <type_traits>

template <bool EnableCtor>
struct test {
  template <bool Enable = EnableCtor, class = std::enable_if_t<Enable>>
  test() {}
  int a;
};

int main() {
    test<false> t {.a = 0};
}
Run Code Online (Sandbox Code Playgroud)

GCC 和 CLang 都不会编译此代码。因此,尽管这里没有实例化的构造函数,但该类不是聚合。

构造函数模板是否被视为“声明的构造函数”?对于这种情况,标准有何规定?

Bar*_*rry 5

聚合的定义发生了很大变化,但这里的相关部分却相当稳定。[dcl.init.aggr]中的 C++20 措辞表示:

聚合是一个数组或一个类 ([class] )

  • 没有用户声明或继承的构造函数([class.ctor]),
  • 没有私有或受保护的直接非静态数据成员([class.access]),
  • 没有虚函数([class.virtual]),并且
  • 没有虚拟、私有或受保护的基类 ([class.mi])。

请注意,它只是说没有声明构造函数,句号。关于构造函数对于类模板的特定专业化是否可行并不是什么微妙的事情。根本就没有。

所以给出这样的事情:

template <bool B>
struct X {
    int i;
    X(int i) requires B;
};
Run Code Online (Sandbox Code Playgroud)

X<false>仍然不是一个聚合,即使它唯一声明的构造函数对于该专业化来说是不可行的。没关系。聚合性只是声明的一个属性。