Let's look at this sample of code:
class D
{
public:
constexpr D(int val) : i(val) { };
~D() { };
private:
int i;
};
D d(3);
According to the documentation, D should be constant initialized:
Only the following variables are constant initialized: [...]
2. Static or thread-local object of class type that is initialized by a constructor call, if the constructor is constexpr and all constructor arguments (including implicit conversions) are constant expressions, and if the initializers in the constructor's initializer list and the brace-or-equal initializers of the class members only contain constant expressions.
Indeed, d
is initialized by constructor call, the constructor of D
is constexpr
and my argument (3
) is a constant expression.
However, to specify to the compiler the value of a variable can be evaluated at compile time, it is possible to use constexpr
specifier. But, in this case, it won't compile because D
is not a LiteralType because it define a non-trivial constructor.
So, in my snippet, is d
really constant initialized? If so, why can't I use constexpr
specifier?
A default constructor is a constructor that either has no parameters, or if it has parameters, all the parameters have default values. If no user-defined constructor exists for a class A and one is needed, the compiler implicitly declares a default parameterless constructor A::A() .
It's not mandatory to define default constructor, but if you are writing Hibernate persistent class, JPA entities, or using the Spring framework to manage object creation and wiring dependencies, you need to be a bit careful.
To value-initialize an object of type T means: — if T is a class type (clause 9) with a user-declared constructor (12.1), then the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);
For example, all members of class type, and their class-type members, must have a default constructor and destructors that are accessible. All data members of reference type and all const members must have a default member initializer.
So, in my snippet, is
d
really constant initialized? If so, why can't I useconstexpr
specifier?
Yes, it will be constant initialized. As you've quoted, constant initialization doesn't need the type to be a LiteralType. But constexpr
does need it. Your type is not a LiteralType, so it cannot be a constexpr
. But the type and constructor call fulfills the requirements of being constant initialization.
Btw., C++20 will have constinit. With this, you can make sure that a variable gets static initialized (which means constant initialization in your case).
You can check out constinit for your example on godbolt, as a further evidence that it compiles successfully, and you can see that the object is initialized at compile-time (not a requirement by the standard, but GCC does it).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With