简体   繁体   中英

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; } { 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?

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.

According to the standard, MyClass is considered an incomplete type when you try to invoke FooValue to initialize Foo5 . Therefore, you cannot use its members as you did.
The type is considered a completely-defined object type (or complete type) at the closing } .
On the other side, the class is regarded as complete within function bodies . That's why Foo5Alt compiles just fine.
See [class.mem]/6 for further details.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM