Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can an object of class type T be constant initialized when T has a non-trivial destructor?

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?

like image 739
Pierre Avatar asked Sep 18 '19 08:09

Pierre


People also ask

What's a default constructor How are an object's data members initialized if a class has only an implicitly defined default constructor?

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() .

Is it always necessary to provide a default constructor for a class Why or why not?

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.

What is value initialized in C++?

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);

Does every class have a default constructor C++?

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.


1 Answers

So, in my snippet, is d really constant initialized? If so, why can't I use constexpr 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).

like image 62
geza Avatar answered Oct 19 '22 06:10

geza