0
votes

What is the rationale for [dcl.constexpr]p5 (http://eel.is/c++draft/dcl.constexpr#5)?

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 ([expr.const]), or, for a constructor, a constant initializer for some object ([basic.start.init]), the program is ill-formed; no diagnostic required.

If a program violated this rule, declaring the offending function constexpr was useless. So what? Isn't it better to accept useless uses of the decl-specifier constexpr instead of triggering undefined behaviour (by no diagnostics required)? In addition to the problem with undefined behaviour we also have the additional complexity of having the rule [dcl.constexpr]p5 in the standard.

An implementation can still provide useful diagnostic messages in some cases that it is able to detect (warnings by convention). Just like in the following case:

int main() { 0; }

The expression in main there is well-formed but useless. Some compilers issue a diagnostic message anyway (and they are allowed to) in the form of a warning.

I understand that [dcl.constexpr]p5 cannot require diagnostics, so i'm not asking about that. I'm just asking about why this rule is even in the standard.

1
So that the implementation can diagnose a never-constexpr function if it wants, but doesn't have to go out of its way to. Similar to early checking of templates. - T.C.
Please include the wording in your question, links may go dead and then the question is not as useful as a reference. - Shafik Yaghmour
@T.C Implementations may diagnose anything they want, no special permission needed. - n. 1.8e9-where's-my-share m.

1 Answers

2
votes

The reason it's ill-formed is because making it ill-formed allows implementations to reject constexpr function definitions that cannot possibly form constant expressions. Rejecting them early means getting more useful diagnostics.

The reason no diagnostic is required is because it may be unrealistic for an implementation to determine that for each and every possible combination of arguments, the result is not a constant expression.

The fact that ill-formed, no diagnostic required, effectively means the same thing as making the behaviour undefined seems to me as if it's unfortunate, but merely picked for lack of a better option. I'd be highly surprised if the intent would actually be to allow any arbitrary run-time behaviour, but there is no concept of "may be diagnosed as an error, but if not, must behave as specified" for any language feature in C++.