不,因为一个初始化子句不一定是某个的一部分初始化器。这里有问题的语法项目是这个版本的参数声明 https://eel.is/c++draft/dcl.fct#nt:parameter-declaration:
attribute-specifier-seqopt thisopt decl-specifier-seq declarator = initializer-clause
施加适量的头发分裂,这意味着form带有默认参数的参数声明与初始化类似,但仍有细微的不同。最明显的区别是,如果使用实际参数,则默认参数将被忽略。不太明显的是,参数实际上不能被常量初始化,即使它的默认参数是常量表达式。即使该函数仅在编译时求值,这一点仍然成立。下面是一些代码,显示了含义上的细微差别:
#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
}
如你看到的here https://godbolt.org/z/qYjo94e6o,这只会生成一个运行时调用f(int const&)
没有人g(int)
。尽管其他评估的参数实际上是编译时常量,但您既不能使用也不能这样指定它们:
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);