简体   繁体   中英

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

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM