Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

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?

like image 891
Michael Anderson Avatar asked May 03 '18 07:05

Michael Anderson


People also ask

What is constexpr used for?

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.

Can constexpr functions call non constexpr functions?

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.

Can a member function be constexpr?

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.

Is constexpr implicitly const?

In C++11, constexpr member functions are implicitly const.


1 Answers

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.

like image 163
StoryTeller - Unslander Monica Avatar answered Sep 19 '22 08:09

StoryTeller - Unslander Monica