绑定initializer_list被g++接受但clang拒绝,孰是孰非?
C++默认实参绑定非const左值引用的标准合规性问题
测试代码与编译表现
以下代码在不同编译器下表现存在差异:
#include <vector> template<typename T> void foo(T i, std::vector<int> &v = {}) { } int main() { std::vector<int> v; foo(3, v); }
- g++ 14.2.1可正常编译该代码
- clang 19.1.7编译时报错:
non-const lvalue reference to type 'std::vector<int>' cannot bind to an initializer list temporary
补充说明:若调用时省略第二个参数(即foo(3)),两款编译器均会拒绝编译,这符合预期——此时确实是尝试将非const左值引用绑定到临时右值,违反标准规则。
标准合规性分析
clang的处理符合C标准,g的行为属于非标准扩展。
根据C标准,函数模板的默认实参需要在模板定义点完成语义检查,而非仅在调用点判断是否使用该默认实参。在定义foo时,默认实参{}会被解析为std::vector<int>临时对象,而C标准明确禁止非const左值引用绑定到临时对象。无论这个默认实参在实际调用中是否被使用,模板定义时的这个绑定错误已经存在,编译器应当拒绝编译。
g放宽了这一标准限制,允许定义时存在无效默认实参,只要实际调用未用到它,但这种行为并不符合C标准的规定。
内容的提问来源于stack exchange,提问作者Tootsie
相关产品推荐
相关产品推荐

