I just a have a problem in understanding when the compiler marks the constructor as constexpr.
If I write the following program:
struct S{ S() {}; }
constexpr S s{ };
Does this mean that the default constructor is marked as constexpr?
CodePudding user response:
An implicitly-defined constructor is a constructor defined by the compiler implicitly when some contexts are encountered (see below). But, an explicitly-defined constructor is a constructor defined by the user, not by the compiler.
Now per [class.default.ctor]/4:
A default constructor that is defaulted and not defined as deleted is implicitly defined when it is odr-used ([basic.def.odr]) to create an object of its class type ([intro.object]), when it is needed for constant evaluation ([expr.const]), or when it is explicitly defaulted after its first declaration. The implicitly-defined default constructor performs the set of initializations of the class that would be performed by a user-written default constructor for that class with no ctor-initializer and an empty compound-statement. If that user-written default constructor would be ill-formed, the program is ill-formed. If that user-written default constructor would satisfy the requirements of a constexpr constructor ([dcl.constexpr]), the implicitly-defined default constructor is constexpr [..]
This paragraph just tells you that the non-deleted defaulted default constructor is implicitly-defined when it's odr-used or needed for constant evaluation or explicitly-defaulted after its first declaration.
Also, it tells you that that implicitly-defined constructor is the same as the user-written default constructor with an empty body and no member-initializer-list.
Then, it tells you that it's defined as constexpr
if its corresponding user-written default constructor satisfies all of the [dcl.constexpr]/3 conditions.
That's, an implicitly or explicitly defaulted constructor will be implicitly-defined as constexpr
if all requirements of [dcl.constexpr]/3 are met. On other hand, neither explicitly-defined nor explicitly-declared constructor is implicitly-defined as constexpr even if it satisfies all of [dcl.constexpr]/3 that's because you explicitly defined it. But if you explicitly mark it as constexpr
, it will be a constexpr
constructor, meanwhile, it shall satisfy all of [dcl.constexpr]/3 conditions.
So in your example:
struct S{ S() {}; }
constexpr S s{ };
That's ill-formed just because S
is not a literal type and you're trying to call a non-constexpr
constructor in a constant expression context which is not allowed per [const.expr]/(5.2)
CodePudding user response:
A constructor is only (potentially) implicitly constexpr
if either the whole constructor itself is implicitly declared or if it is defaulted with = default
on its first declaration.
You are manually declaring the constructor and you are not defaulting it, so it will only be constexpr
if you add the constexpr
specifier to the declaration.
The shown constructor is therefore not constexpr
and as a consequence constexpr S s{ };
will fail to compile because the initialization would call a non-constexpr
constructor which isn't allowed in a constant expression. constexpr
on a variable declaration does however require the initialization of the variable (including the evaluation of the initializer(s)) to be a constant expression.
CodePudding user response:
The other answers give details about why the constructor in your snippet is not constexpr
, and that's good to know.
However, I think, given how the question is phrased, that another answer is required.
Does declaring a
constexpr
object marks the constructor asconstexpr
This means that you are thinking of the idea that the way you declare an object can affect the definition of its class.
That is not the case: once you write down the definition of a class, that's the definition, at it won't be altered by whatever objects of that class you declare/define.
In more complex scenario, when templates are involved, the code generated for a template class can depend on the objects you create; but the point is that you'd be talking of a templates class, whereas your question is about a class.