问题
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?
回答1:
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.
回答2:
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.
来源:https://stackoverflow.com/questions/41048474/c11-cant-define-constexpr-literal-using-constexpr-function