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. Theconsteval
specifier shall be applied only to the declaration of a function or function template. A function or static data member declared with theconstexpr
orconsteval
specifier is implicitly an inline function or variable ([dcl.inline]). If any declaration of a function or function template has aconstexpr
orconsteval
specifier, then all its declarations shall contain the same specifier.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.
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.