No, because an initializer-clause is not necessarily part of an initializer. The grammar item in question here is this version of the parameter-declaration:
attribute-specifier-seqopt thisopt decl-specifier-seq declarator = initializer-clause
Applying just the right amount of hair-splitting, this means that the form of a parameter declaration with a default argument is similar to an initialization, but it is still subtly different. The most obvious difference being that the default argument is ignored if an actual argument is used. Less obvious is that a parameter cannot actually be constant-initialized, even if its default argument is a constant expression. This remains true even if the function is only evaluated at compile time. Here is some code that shows the subtle differences in meaning:
#include <random>
// R may be evaluated at compile time and must be constant-initialized
static constexpr int R = 0;
// f may be evaluated at compile time
constexpr int f(const int& r = R) { return r + 42; }
// I must be constant- *or* zero-initialized, even if only evaluated at runtime
constinit const int I = f();
// g is an "immediate function": it may not be evaluated at runtime
consteval int g(int i = I) { return i - 42; }
int main() {
// A variable that may not appear in constant expressions,
// because it is not constant-initialized
const int not_const = std::rand();
static int x1 = f(); // OK, constant initialization
// constexpr int x2 = f(not_const); // error, not constant-initialized
int x3 = f(); // OK, f() evaluated at compile time
int x4 = f(not_const); // OK, evaluated at runtime
static int y1 = g(); // OK
// constexpr int y2 = g(not_const); // error
int y3 = g(); // OK
// int y4 = g(not_const); // error
}
As you can see here, this generates only one runtime call to f(int const&)
and none to g(int)
. Even though the parameters for the other evaluations were effectively compile-time constants, you can neither use nor specify them as such:
constexpr int f(const int& r = R) {
// constexpr int x = r; // error, not a constant expression
return r + 42;
}
consteval int g(int i = I) {
// constexpr int y = i; // still not a constant expression!
return i - 42;
}
// Also not allowed:
// consteval void h(constexpr int x = 0, constinit int y = 1);
g()
is equivalent tog(I)
and sog(0)
. – Radtkeconstexpr
, and the there is the above equivalence. – Radtke