3

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
bitmask
  • 32,434
  • 14
  • 99
  • 159
  • This is sparked by this [chat discussion](https://chat.stackoverflow.com/rooms/215752/discussion-between-holyblackcat-and-bitmask). I suppose other people can join that chat. – bitmask Jun 11 '20 at 15:22
  • There are similar rules about template which should have potential type/parameter for which it is instantiable (forbidding `static_assert(false);`). – Jarod42 Jun 11 '20 at 19:22

1 Answers1

6

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.

cigien
  • 57,834
  • 11
  • 73
  • 112