C++编译器是否真的符合零大小数组SFINAE规则?
问题解答
首先明确结论:Clang的处理符合C++标准,GCC和ICC的行为不符合标准要求。
背后的原因拆解如下:
- SFINAE的核心逻辑是:模板参数替换阶段,若在「直接语境」中出现无效类型或表达式,只会排除当前重载,不会触发全局编译错误。
- 根据C++标准定义,创建零大小数组类型属于SFINAE覆盖的替换错误范畴。你的代码中,
Failer<I>是零大小数组的别名,当实例化y<I>时,替换得到Char<I>[0]这种无效类型——这个错误发生在函数模板参数的直接语境中,因此该重载应该被SFINAE规则排除。 - Clang正确识别了这个替换错误,排除了
Failer版本的重载,选择了int版本,完全符合标准。 - GCC的问题在于,它把零大小数组的类型错误判定为全局编译错误,而非SFINAE允许的替换失败,违背了标准规则。
- ICC则是依赖了非标准扩展:它将零大小数组视为有效类型(类似C语言的编译器扩展),因此认为
Failer版本的重载可行并选择它,但这不符合C++标准对数组类型的强制要求。
内容的提问来源于stack exchange,提问作者ivanovmp
相关产品推荐
相关产品推荐

