Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does specifying constexpr on constructor automatically makes all objects created from it to be constexpr?

Here is my code:

class test{     public:     constexpr test(){      }      constexpr int operator+(const test& rhs){         return 1;     } };    int main(){      test t;                         //constexpr word isn't necessary     constexpr int b = t+test();     // works at compile time!       int w = 10;                     // ERROR constexpr required     constexpr int c = w + 2;        // Requires w to be constexpr     return 0; } 

I notice that it worked even though I didn't specify test to be constexpr. I tried replicating the result by doing the same with int but i get errors. Specifically, it wants my int w inside the constexpr int c = w + 2; to be constexpr. From my first attempt which is using test, Did it work because of the reason that i used constexpr on the constructor already? If that is the case then would it good to assume that all classes that have constexpr on their constructors will result to all objects instantiated or created with it to be constexpr?

Bonus question:

If I have a constexpr constructor, is it bad to do something like ? test * t = new test(); ?

like image 468
Carlos Miguel Colanta Avatar asked Jul 13 '15 04:07

Carlos Miguel Colanta


People also ask

Can constructors be constexpr?

A constexpr function must accept and return only literal types. A constexpr function can be recursive. It can't be virtual. A constructor can't be defined as constexpr when the enclosing class has any virtual base classes.

Is constexpr a default constructor?

defaulted default constructor cannot be constexpr because the corresponding implicitly declared default constructor would not be constexpr.

Is constexpr guaranteed?

A constexpr function that is eligible to be evaluated at compile-time will only be evaluated at compile-time if the return value is used where a constant expression is required. Otherwise, compile-time evaluation is not guaranteed.

Is constexpr always static?

constexpr int a = 2; Static specifies the lifetime of the variable. A static constexpr variable has to be set at compilation, because its lifetime is the the whole program. Without the static keyword, the compiler isn't bound to set the value at compilation, and could decide to set it later.


1 Answers

Having a constexpr constructor does not make declarations of that variable automatically constexpr, so t is not a constexpr. What is going on in this case is that you are calling a constexpr function, this line:

constexpr int b = t+test();  

can be viewed as follows:

constexpr int b = t.operator+( test() );  

So then the question is whether test() is a constant expression, which it is since the constructor is constexpr and does not fall under any of the exceptions under the draft C++11 standard section 5.19 [expr.const] paragraph 2 which says:

A conditional-expression is a core constant expression unless it involves one of the following as a potentially evaluated subexpression [...]

and includes the following bullet:

  • an invocation of a function other than a constexpr constructor for a literal class or a constexpr function [ Note: Overload resolution (13.3) is applied as usual —end note ];

[...]

  • an invocation of a constexpr constructor with arguments that, when substituted by function invocation substitution (7.1.5), do not produce all constant expressions for the constructor calls and full-expressions in the mem-initializers

  • an invocation of a constexpr function or a constexpr constructor that would exceed the implementationdefined recursion limits (see Annex B);

We can see this more readily by making some small changes to test by introducing a member variable x:

class test{     public:     constexpr test(){      }      constexpr int operator+(const test& rhs) const {         return x + 1  ;     }      int x = 10 ; }; 

Attempting to access it in operator + and we can see that the following line now fails:

constexpr int b = t+test(); 

with the following error from clang (see it live):

error: constexpr variable 'b' must be initialized by a constant expression constexpr int b = t+test();     // works at compile time!               ^   ~~~~~~~~  note: read of non-constexpr variable 't' is not allowed in a constant expression     return x + 1  ;            ^ 

It fails because t is not a constexpr variable and therefore its subobjects are also not constexpr variables.

Your second example:

 constexpr int c = w + 2;   

does not work because it falls under one of the exceptions in the draft C++11 standard section 5.19 [expr.const] :

  • an lvalue-to-rvalue conversion (4.1) unless it is applied to

    [...]

    • a glvalue of integral or enumeration type that refers to a non-volatile const object with a preceding initialization, initialized with a constant expression, or
like image 141
Shafik Yaghmour Avatar answered Sep 20 '22 18:09

Shafik Yaghmour