显式默认构造函数与显式模板实例化:Clang/GCC编译差异及合规性判断
g拒绝原代码的行为是否符合C标准?
首先看原代码:
template <typename> struct S { S(); }; // extern template struct S<int>; template <typename T> S<T>::S() = default; template S<int>::S();
现象
- clang++可正常编译该代码;
- g++编译报错,提示显式默认的
S<int>::S()已存在定义; - 取消注释
extern template struct S<int>;后,g++也可正常编译。
标准分析
根据C++标准的相关条款:
- 成员函数模板的显式默认:成员函数模板允许被显式默认(
= default),其特化的定义会在实例化时生成,这属于标准允许的语法(见[temp.mem.func])。 - 显式实例化定义的规则:显式实例化定义(
template S<int>::S();)的作用是强制实例化指定的函数特化,只要该特化未被显式特化,就不会与现有定义冲突(见[temp.explicit]/11)。 - 隐式实例化的触发条件:类模板特化的成员函数只有在被ODR使用时才会触发隐式实例化,而显式实例化定义本身是强制实例化操作,并非重复定义。
g的报错逻辑认为无extern template时S<int>::S()已通过隐式实例化生成定义,但实际上显式实例化定义是合法的强制实例化操作,并未违反标准。clang的行为符合标准要求,而g的拒绝属于编译器实现缺陷。
结论
g拒绝原代码的行为**不符合C标准**,该代码是合法的C++代码。
内容的提问来源于stack exchange,提问作者Vittorio Romeo
相关产品推荐
相关产品推荐

