Function A constexpr can be called in any context, constant expression or not. (And your sample_method_second is not even constexpr .) But the constexpr object must be evaluated at compile time.
So what sample_method_second does, ask the compiler to use this to get the result of sample_method_first at compile time. Clearly this is not possible.
The difference is that in the first example, the scope of main allows the compiler to call the method on sample_object . But the ability to evaluate the value of one object does not apply to all potential objects in the program, which is what sample_method_second does.
The solution (well, except to create a sample_method_first that is independent of this using static ) should not declare sample_variable as constexpr . If you use it in a way that constexpr requires, then your design is erroneous because one member function really needs several (potentially infinite) implementations in the final program.
Remember that each potential different value of the legitimate variable constexpr can create a new instance of the template, otherwise an organized compilation of switch or halt with static_assert . Try doing this retroactively at runtime!
As to why the first case is allowed:
sample_struct sample_object; constexpr int sample_variable = sample_object.sample_method();
What happens here is a call to the constexpr function, and the rule for this excludes
- a call to a function other than the constexpr constructor for a literal class, a constexpr function, or an implicit call to a trivial destructor (12.4)
There is simply no requirement that the object be constexpr , because if something needs to be constant in order to evaluate the inside of the function or use the result of the function, the evaluation will be erroneous according to one of the other rules, such as the lvalue-to-rvalue conversion. You wonβt be able to modify sample_method to actually access anything, and you will complain that sample_object not declared constexpr or its address is not constant if you try to use this value directly.