代码之家  ›  专栏  ›  技术社区  ›  bielu000

CRTP基私有构造函数和派生的friend类使用C++17和统一初始化导致编译错误

  •  3
  • bielu000  · 技术社区  · 2 年前

    我有以下代码:

    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();
    } 
    

    由于某种原因,在使用C++17时,由于“x”变量的“不可编译”初始化,编译失败。编者说:

    Base::Base()[with T=Derived]“在这个上下文中是私有的

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

    Compiler explorer

    1 回复  |  直到 2 年前
        1
  •  3
  •   HolyBlackCat    2 年前

    显然地 Derived 是自C++17以来的聚合 Derived{} 是一个聚合初始化。(基类) weren't allowed in aggregates pre-C++17 ,现在允许使用公共非虚拟基地。)

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

    解决办法是增加 Derived() {} 衍生 阻止它成为一个整体。