CRTP base private constructor and derived friend class cause compilation error using C++17 和统一初始化

CRTP base private constructor and derived friend class cause compilation error using C++17 and uniform initialization

我有以下代码:

struct B
{
  B(int) {}
};

template <typename T>
class Base : public B
{
  friend T;
  Base() : B(1) {}
};

class Derived : public Base<Derived>
{
public:
    void do_sth() const {}
};

int main()
{
  auto x = Derived{}; //Compiles only when using C++11
  auto x1 = Derived(); //Compiles using C++17/20 flag
  x.do_sth();
  x1.do_sth();
} 

出于某种原因,由于 'x' 变量的 'non-compilable' 初始化,使用 C++17 编译失败。编译器说:

Base::Base() [with T = Derived]' is private within this context

但如您所见,下面我正在创建一个相同类型的对象,但这次我没有使用统一初始化。 x1 变量可以使用 C++11 或 C++17 标准编译,但 'x' 变量只能在 C++11 模式下编译。这是为什么?导致此问题的标准发生了什么变化?

Compiler explorer

显然 Derived 是自 C++17 以来的聚合,因此 Derived{} 是聚合初始化。 (基础 类 weren't allowed in aggregates pre-C++17,现在 public non-virtual 基础是允许的。)

意思是Base::Base()是由调用者直接调用的(main()),而不是Derived.

解决方案是将Derived() {}添加到Derived以阻止它成为聚合。