c++c++20inlineconstexpr-function

Where in the C++20 standard (N4860) does it say that an inline function must be defined before its use in a translation unit?


[dcl.constexpr]/1:

The constexpr specifier shall be applied only to the definition of a variable or variable template or the declaration of a function or function template. The consteval specifier shall be applied only to the declaration of a function or function template. A function or static data member declared with the constexpr or consteval specifier is implicitly an inline function or variable ([dcl.inline]). If any declaration of a function or function template has a constexpr or consteval specifier, then all its declarations shall contain the same specifier.

Example 1

constexpr void square(int &x);  // OK, declaration
constexpr int bufsz = 1024;     // OK, definition
constexpr struct pixel {        // error: pixel is a type
  int x;
  int y;
  constexpr pixel(int);         // OK, declaration
};
constexpr pixel::pixel(int a)
  : x(a), y(x)                  // OK, definition
  { square(x); }
constexpr pixel small(2);       // error: square not defined, so small(2) <<<<<<<<<<<<<<<<<<<<
                                // not constant ([expr.const]) so constexpr not satisfied

constexpr void square(int &x) { // OK, definition
  x *= x;
}
constexpr pixel large(4);       // OK, square defined
int next(constexpr int x) {     // error: not for parameters
     return x + 1;
}
extern constexpr int memsz;     // error: not a definition

I presume that the error highlighted above with the characters <<<<<<<<<<<<<<< is related with the third sentence in [dcl.constexpr]/1, that is:

A function or static data member declared with the constexpr or consteval specifier is implicitly an inline function or variable ([dcl.inline]).

But I couldn't find anything in C++20 (N4860) that would establish the assertion that an inline function has to be defined before its use in a translation unit.


Solution

  • constexpr pixel small(2); is ill-formed, because the initialization of a variable declared constexpr shall be a constant expression and an expression is disqualified from being a constant expression per [expr.const]/5.3 if a call to an undefined constexpr function is made in it. In your case the call to square in small's constructor call is the cause.

    It isn't specified well when exactly the function needs to be defined (see CWG issue 2166), but in either reasonable interpretation, square in your example is not defined before the relevant point, which is either the lexical point of the call itself or the lexical point of the (head of the) constant expression itself (i.e. at small's definition).


    This is specific to the consequences of constexpr and has nothing to do with inline. An inline function generally does not have to be defined before its use in a translation unit. It just has to be defined somewhere in the translation unit.