函数默认参数值取决于 C++ 中的参数名称
Function default argument value depending on argument name in C++
如果在C++中定义了一个新的变量,那么在初始化表达式中可以使用变量名,例如:
int x = sizeof(x);
那么函数参数的默认值呢?是否允许在那里通过名称引用参数?例如:
void f(int y = sizeof(y)) {}
此函数在 Clang 中被接受,但在 GCC 中被拒绝并出现错误:
'y' was not declared in this scope
演示:https://gcc.godbolt.org/z/YsvYnhjTb
这里是哪个编译器?
根据 C++17 标准(11.3.6 默认参数)
9 A default argument is evaluated each time the function is called
with no argument for the corresponding parameter. A parameter shall
not appear as a potentially-evaluated expression in a default
argument. Parameters of a function declared before a default
argument are in scope and can hide namespace and class member name
它提供了以下示例:
int h(int a, int b = sizeof(a)); // OK, unevaluated operand
所以,这个函数声明
void f(int y = sizeof(y)) {}
是正确的,因为在此表达式 sizeof(y)
中,y
不是计算的操作数,基于 C++17 8.3.3 Sizeof:
1 The sizeof operator yields the number of bytes in the object
representation of its operand. The operand is either an expression,
which is an unevaluated operand (Clause 8), or a parenthesized
type-id.
和C++17 6.3.2声明点:
1 The point of declaration for a name is immediately after its
complete declarator (Clause 11) and before its initializer (if any),
except as noted below.
代码没有出现格式错误,因此 Clang 没问题。
[basic.scope.pdecl]
1 The point of declaration for a name is immediately after its complete declarator ([dcl.decl]) and before its initializer (if any), except as noted below.
这是正在讨论的臭名昭著的段落。我把它带到这里只是为了提到“除了下面提到的”不包括任何默认参数的提及。所以 y
是在 = sizeof(y)
.
之前声明的
另一个相关段落是
[dcl.fct.default]
9 A default argument is evaluated each time the function is called with no argument for the corresponding parameter. A parameter shall not appear as a potentially-evaluated expression in a default argument. Parameters of a function declared before a default argument are in scope and can hide namespace and class member names.
sizeof(y)
没有潜在的评估,所以这也很好。
鉴于第一段使 y
可用作名称,并且其使用方式并非非法,因此一定是 GCC 的某些怪癖拒绝了该代码。
虽然就我个人而言,我并不认为这是一个很大的损失。这不是最实用的代码。
如果在C++中定义了一个新的变量,那么在初始化表达式中可以使用变量名,例如:
int x = sizeof(x);
那么函数参数的默认值呢?是否允许在那里通过名称引用参数?例如:
void f(int y = sizeof(y)) {}
此函数在 Clang 中被接受,但在 GCC 中被拒绝并出现错误:
'y' was not declared in this scope
演示:https://gcc.godbolt.org/z/YsvYnhjTb
这里是哪个编译器?
根据 C++17 标准(11.3.6 默认参数)
9 A default argument is evaluated each time the function is called with no argument for the corresponding parameter. A parameter shall not appear as a potentially-evaluated expression in a default argument. Parameters of a function declared before a default argument are in scope and can hide namespace and class member name
它提供了以下示例:
int h(int a, int b = sizeof(a)); // OK, unevaluated operand
所以,这个函数声明
void f(int y = sizeof(y)) {}
是正确的,因为在此表达式 sizeof(y)
中,y
不是计算的操作数,基于 C++17 8.3.3 Sizeof:
1 The sizeof operator yields the number of bytes in the object representation of its operand. The operand is either an expression, which is an unevaluated operand (Clause 8), or a parenthesized type-id.
和C++17 6.3.2声明点:
1 The point of declaration for a name is immediately after its complete declarator (Clause 11) and before its initializer (if any), except as noted below.
代码没有出现格式错误,因此 Clang 没问题。
[basic.scope.pdecl]
1 The point of declaration for a name is immediately after its complete declarator ([dcl.decl]) and before its initializer (if any), except as noted below.
这是正在讨论的臭名昭著的段落。我把它带到这里只是为了提到“除了下面提到的”不包括任何默认参数的提及。所以 y
是在 = sizeof(y)
.
另一个相关段落是
[dcl.fct.default]
9 A default argument is evaluated each time the function is called with no argument for the corresponding parameter. A parameter shall not appear as a potentially-evaluated expression in a default argument. Parameters of a function declared before a default argument are in scope and can hide namespace and class member names.
sizeof(y)
没有潜在的评估,所以这也很好。
鉴于第一段使 y
可用作名称,并且其使用方式并非非法,因此一定是 GCC 的某些怪癖拒绝了该代码。
虽然就我个人而言,我并不认为这是一个很大的损失。这不是最实用的代码。