The accepted answer in literal class compile error with constexpr constructor and function (differ vc, g++) shows that in C++14 there is a difference in the way constexpr int A::a()
and constexpr A::a() const
can be used. i.e. constexpr
on a member function does not imply that the function does not change the object it acts on.
The given example is:
struct A { constexpr A() {} constexpr int a() {return 12; } constexpr int b() const {return 12; } }; int main() { constexpr A a; // DOES NOT COMPILE as a() is not const // constexpr int j = a.a(); const int k = a.b(); // Fine since b() is const }
To me the constexpr
on a()
seems useless. Is there a concrete use for constexpr
on a non-const
member function?
constexpr indicates that the value, or return value, is constant and, where possible, is computed at compile time. A constexpr integral value can be used wherever a const integer is required, such as in template arguments and array declarations.
A call to a constexpr function produces the same result as a call to an equivalent non- constexpr function , except that a call to a constexpr function can appear in a constant expression. The main function cannot be declared with the constexpr specifier.
const can only be used with non-static member functions whereas constexpr can be used with member and non-member functions, even with constructors but with condition that argument and return type must be of literal types.
In C++11, constexpr member functions are implicitly const.
constexpr
means "can be used where a constant expression is required". The "implied const" for declared objects doesn't mean we can't have non-const objects in other contexts. For instance, a somewhat contrived example, created from your own:
template<int> struct foo { }; struct A { int i = 0; constexpr A() {} constexpr int a() { return i; } constexpr int b() const {return 12; } constexpr A& c() { ++i; return *this; } }; int main() { foo<A{}.c().a()> f1; }
Obviously the template argument must be a constant expression. Now, A{}
is a prvalue of a literal type with a constexpr c'tor, and it's a non-const object. The member function is allowed to modify this "constant" because the entire computation can collapse to a constant expression at compile time. That's the rationale for the rules, on one foot.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With