Reputation: 4679
Consider the following class:
class Foo {
int a, b;
public:
Foo() : a{1}, b{2} {} // Default ctor with member initializer list
//Foo() : a{1}, b{2} = default; // Does not work but why?
};
(Edit: because it was mentioned in a couple of answers - I'm aware of in-class member initializiers, but that's not the point here)
I think the second ctor definition would be more elegant and fit better into modern C++ code (see also why you should use =default
if you have to be explicit about using the default semantics). However, no common compiler seems to accept it. And cppreference is silent about it.
My first thought was that a member initializer list in a way changes the "default semantics" as explained in the linked FAQ, because it may or may not default-construct members. But then we would have the same problem for in-class initializers, just that here Foo() = default;
works just fine.
So, why is it disallowed?
Upvotes: 8
Views: 565
Reputation: 180980
Doing a{1}, b{2}
means you no longer can specify it as default
. A default function per [dcl.fct.def.default]/1 is defined as
A function definition whose function-body is of the form
= default;
is called an explicitly-defaulted definition.
And if we check what a function-body is in [dcl.fct.def.general]/1 we see that it contains a ctor-initializer which is a mem-initializer-list
This means you can't initialize members if you want a default definition provided by the compiler.
What you can do to work around this is to specify the default values in the class directly, and then declare the constructor as default like
class Foo {
int a{1}, b{2};
public:
Foo() = default;
};
Upvotes: 7
Reputation: 6139
This doesn't directly answer the question, however it is the c++ "way" is to use the default member initializer instead, that it
class Foo {
int a = 1, b = 2;
public:
Foo() = default;
};
The syntax you purpose is simply not a default, per se, constructor anymore.
Upvotes: 3
Reputation: 170193
= default;
is an entire definition all on its own. It's enforced, first and foremost, grammatically:
[dcl.fct.def.general]
1 Function definitions have the form
function-definition: attribute-specifier-seqopt decl-specifier-seqopt declarator virt-specifier-seqopt function-body function-body: ctor-initializeropt compound-statement function-try-block = default ; = delete ;
So it's either a member initializer list with a compound statement, or just plain = default;
, no mishmash.
Furthermore, = default
means something specific about how each member is initialized. It means we explicitly want to initialize everything like a compiler provided constructor would. That is in contradiction to "doing something special" with the members in the constructor's member initializer list.
Upvotes: 11
Reputation: 1757
It's disallowed because what you're trying to do by definition means it's no longer a default constructor. And there's a more elegant way of accomplishing what you want anyway:
class Foo {
int a {1};
int b {2};
public:
Foo() = default;
};
Upvotes: 2