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();
?
The constexpr key word by my experiments in this answer more or less instructs the compiler that it must be able to statically resolve all codepaths given in that call. That is, at least right now (it would appear), everything must be declared constexpr along that codepath otherwise it will fail. For example, in your code, the initial constexpr assignment to b will fail if you don't declare the operator or constructor constexpr. It appears that the constexpr only takes effect when you're assigning to a variable that is declared constexpr, otherwise it seems to only serve as an adviser to the compiler that the codepath can be optimized via static evaluation, but it's not guaranteed to do it if you don't explicitly instruct it with a constexpr variable assignment.
That being said, it would appear that declaring a constructor constexpr has no affect under normal circumstances. The machine code below was produced with the following command line:
And so your b assignment produces this code:
However, if you remove the constexpr declaration on the b variable:
It appears to be handled as if the operator and constructor weren't declared constexpr, but this is a situation where you should consult the specifics about your compiler, really.
The effect that a
constexpr
constructor has on the class type can be read in the C++ StandardSo
constexpr
constructors means that static initialization can be performed and uses like this one are possible :The mere fact that
test
is a literal class does not mean all its instances will be constant expressions:Demo
In the example above the instance
a
was not declared as a constant so even thougha
could be aconstexpr
constant, it's not one (hence it can be modified).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:can be viewed as follows:
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 section5.19
[expr.const] paragraph2
which says:and includes the following bullet:
We can see this more readily by making some small changes to
test
by introducing a member variablex
:Attempting to access it in
operator +
and we can see that the following line now fails:with the following error from clang (see it live):
It fails because
t
is not a constexpr variable and therefore its subobjects are also not constexpr variables.Your second example:
does not work because it falls under one of the exceptions in the draft C++11 standard section
5.19
[expr.const] :