问题
The standard on constexpr functions states under point 5 of [decl.constexpr]:
For a non-template, non-defaulted constexpr function or a non-template, non-defaulted, non-inheriting constexpr constructor, if no argument values exist such that an invocation of the function or constructor could be an evaluated subexpression of a core constant expression (5.19), the program is ill-formed; no diagnostic required.
It goes on to give the following example for this:
constexpr int f(bool b){ return b ? throw 0 : 0; } // OK
constexpr int f() { return f(true); } // ill-formed, no diagnostic required
What I take from this is that functions with empty argument lists are no-diagnostic ill-formed. This strikes me as extremely bizarre, such that I suspect that my understanding is incorrect. For instance, would this also be ill-formed:
constexpr int g() { return 0; } // ill-formed?
If so, what is the rationale behind this, and if not what does the qualification mean / when does a constexpr function become ill-formed?
Presumably the following are fine?
constexpr int h(int x) { return x; } // presumably fine?
constexpr int l = h(42); // also fine
回答1:
The rationale for this rule is that there should be at least one context where the function can be evaluated in a constexpr
context. e.g. given:
constexpr int f(bool b){ return b ? throw 0 : 0; } // OK
constexpr int f() { return f(true); } // ill-formed, no diagnostic required
There is no way to invoke f()
in a constexpr
context, since all paths through this function will end in an expression that is not a core constant expression.
A compiler would have to evaluate all possible calls to see if there is any way the function is usable in a constexpr
context. This is not easily diagnosable in general, so the language says it's ill-formed-no-diagnostic-required, i.e. you've done something wrong, but the compiler can't diagnose it.
Note that if the zero argument overload of f
was the following:
constexpr int f() { return f(false); } // ok
that would be perfectly fine, since the evaluation ends in a core-constant-expression.
Similarly, this function:
constexpr int g() { return 0; } // ok
as well as this one:
constexpr int h(int x) { return x; } // ok
constexpr int l = h(42); // ok
are fine, since g
and h
can be invoked in a constexpr
context.
The wording of "... if no argument values exist such that ..." might be confusing, as you've asked about the well-formedness of g
. But g
can be invoked with zero arguments, or in other words, with a void
argument, so it's fine.
来源:https://stackoverflow.com/questions/62327672/what-does-decl-constexpr-5-mean-exactly