Home > database >  CRTP base private constructor and derived friend class cause compilation error using C 17 and unifo
CRTP base private constructor and derived friend class cause compilation error using C 17 and unifo

Time:04-02

I've got the following code:

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

For some reason when using C 17 compilation fails due to 'non-compilable' initialization of 'x' variable. Compilator says that:

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

but as you can see, below I'm creating an object of the same type but this time I'm not using uniform initialization. x1 variable can be compiled using both C 11 or C 17 standards, but the 'x' variable is compilable only in C 11 mode. Why is that? What has changed in the standard that causes this problem?

Compiler explorer

CodePudding user response:

Apparently Derived is an aggregate since C 17, so Derived{} is an aggregate initialization. (Base classes weren't allowed in aggregates pre-C 17, now public non-virtual bases are allowed.)

Meaning Base::Base() is invoked directly by the caller (main()), rather than Derived.

The solution is to add Derived() {} to Derived to stop it from being an aggregate.

  • Related