Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++11 - Can't define constexpr literal using constexpr function?

I've run into what seems a counterintuitive error, namely, the inability to assign the value of a constexpr function to a constexpr literal (hope I'm using the language right). Here's the example:

class MyClass {
 public:
  static constexpr int FooValue(int n) { return n + 5; }
  static constexpr int Foo5 = FooValue(5);  // compiler error
  static constexpr int Foo5Alt(void) { return FooValue(5); }  // OK
};

In GCC 4.8.4, Foo5 is flagged for field initializer is not constant. Found this thread suggesting that the older version of GCC might be the culprit. So I plugged it into Coliru (GCC 6.2.0) and got the error 'static constexpr int MyClass::FooValue(int)' called in a constant expression before its definition is complete. I added Foo5Alt() which returns its value as a constexpr function rather than literal, and that compiles fine.

I guess I'm not following why FooValue(5) can't be used as the initializer for Foo5. The definition for FooValue(int n) is complete, isn't it? { return n + 5; } is the entire definition. constexpr denotes an expression that can be fully evaluated at compile time, so why can it not be used to define the return value of a constexpr literal?

What subtlety of C++ am I missing?

like image 570
David R Avatar asked Dec 23 '22 22:12

David R


1 Answers

In C++, inline definitions of member functions for a class are only parsed after the declaration of the class is complete.

So even though the compiler "knows" about MyClass::FooValue(int), it hasn't "seen" its definition yet, and hence it can't be used in a constexpr expression.

A general workaround for this is to stick to constexpr member functions, or declare constexpr constants outside the class.

like image 64
rustyx Avatar answered Mar 09 '23 00:03

rustyx