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

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

The effect that a constexpr constructor has on the class type can be read in the C++ Standard

3.9 Types

(...)

  1. A type is a literal type if it is:

    • it is an aggregate type (8.5.1) or has at least one constexpr constructor or constructor template that is not a copy or move constructor

(...)

So constexpr constructors means that static initialization can be performed and uses like this one are possible :

#include <iostream>

struct test {
    int val; 
    constexpr test(int val) : val(val) { }
};

template<int N>
struct CC {
    double m[N]; 
};

int main()
{
    CC<test(6).val> k; // usage where compile time constant is required
    std::cout << std::end(k.m) - std::begin(k.m) << std::endl; 
    return 0;
}

The mere fact that test is a literal class does not mean all its instances will be constant expressions:

#include <iostream>

struct test {
    int val;
    constexpr test(int val) : val(val) { }
};

int main()
{
    test a(1); 
    ++a.val; 
    std::cout << a.val << std::endl;
    return 0;
}

Demo

In the example above the instance a was not declared as a constant so even though a could be a constexpr constant, it's not one (hence it can be modified).


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:

g++ -std=c++11 -Wall -g  -c main.cpp -o obj/Debug/main.o
g++  -o bin/Debug/TestProject obj/Debug/main.o  

And so your b assignment produces this code:

0x4005bd    push   rbp
0x4005be    mov    rbp,rsp
0x4005c1    mov    DWORD PTR [rbp-0x4],0x1
0x4005c8    mov    eax,0x0
0x4005cd    pop    rbp
0x4005ce    ret

However, if you remove the constexpr declaration on the b variable:

0x4005bd    push   rbp
0x4005be    mov    rbp,rsp
0x4005c1    sub    rsp,0x10
0x4005c5    lea    rax,[rbp-0x5]
0x4005c9    mov    rdi,rax
0x4005cc    call   0x4005ee <test::test()>
0x4005d1    lea    rdx,[rbp-0x5]
0x4005d5    lea    rax,[rbp-0x6]
0x4005d9    mov    rsi,rdx
0x4005dc    mov    rdi,rax
0x4005df    call   0x4005f8 <test::operator+(test const&) const>
0x4005e4    mov    DWORD PTR [rbp-0x4],eax
0x4005e7    mov    eax,0x0
0x4005ec    leave
0x4005ed    ret

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.