Browsing my code I found a part which - I thought - should be a compile time error, but in reality in compiles and runs fine. A simplified version is:
class Base
{
public:
Base(int i)
{}
};
class Derived : public Base
{
public:
//using Base::Base;
};
int main()
{
Derived obj{ 5 };
}
Checking the code snippet in cppinsights, for the line inside main
it generates Derived obj = {Base(5)};
when using c++17 or newer and does not compile with c++14 or older.
In c++14 if I uncomment //using Base::Base;
then the code compiles. This using here is available since C++11 I believe. In this case cppinsights generates Derived obj = Derived{5};
. I can understand the meaning of it.
My questions are
{Base(5)};
mean? What are the curly brackets are used for?using Base::Base;
or they are completely different.Thank you for your help!
EDIT1:
I changed the main()
function to the lines below, just to show what cppinsights "creates" from it
int main()
{
Derived obj1{ 5 }; // OK. cppinsights: Derived obj1 = {Base(5)};
Derived obj2 = {Base(5)}; // OK. cppinsights: {Base(Base(5))};
//Derived obj3 = Base{5}; // error: no viable conversion from 'Base' to 'Derived'
}
Let's start with the second question.
Derived obj{ 5 };
is the list-initialization syntax. The first (and only) expression on that list is used to initialize the Base
member, which requires one conversion (from int
to Base
).
Now, since C++17 Derived
is an aggregate, which means that the list-initialization syntax now uses aggregate initialization. In C++14, the (public) base class prevented Derived
from being an aggregate.
In C++14, the using
statement allowed the Base
ctors to participate in overload resolution when constructing a Derived object
. Base::Base(int)
obviously wins the overload resolution for Derived{5}
.