GCC与Clang对同名参数默认值解析存分歧,孰是孰非?
GCC与Clang对默认参数中同名标识符的解析分歧:哪一方符合C++标准?
结论:Clang的行为符合C++标准,GCC的行为属于非标准扩展
标准规则依据
根据C标准(以C17为例,[dcl.fct.default]第9款):
默认参数的表达式在函数参数的作用域内求值,参数名称的作用域从其声明点开始,包含默认参数的表达式区域。
也就是说,在void foxy(Foxes& foxes = foxes())这个定义中,等号右侧的foxes会优先绑定到左侧的参数名foxes(一个Foxes&类型的引用),而非全局作用域的foxes()函数。由于引用类型无法被调用,这段代码本身是不符合C++标准的非法代码,Clang报错是正确的诊断行为。
GCC的非标准行为
GCC在这里做了特殊处理:它没有让参数名覆盖默认参数表达式中的同名全局函数,而是将右侧的foxes()解析为全局函数。这属于GCC的非标准扩展,不符合C++标准的规定。
关于GCC -Wshadow警告未触发的问题
-Wshadow用于检测标识符被内层作用域同名标识符阴影的情况。按照标准,参数foxes确实阴影了全局函数foxes(),但GCC的-Wshadow目前未覆盖默认参数表达式这个场景,属于警告机制的遗漏,相关问题在GCC的bug跟踪系统中已有记录。
修复方案
要让代码在两款编译器下都正常编译,有两种可行方式:
- 修改参数名称,避免与全局函数同名:
void foxy(Foxes& fs = foxes()) { (void)fs; } - 明确指定全局作用域的函数,消除歧义:
void foxy(Foxes& foxes = ::foxes()) { (void)foxes; }
内容的提问来源于stack exchange,提问作者Bulletmagnet
相关产品推荐
相关产品推荐

