What is the use of a constexpr on a non-const member function?

  • A+
Category:Languages

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 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.

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: