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?
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.