非constexpr模板特化声明跟随constexpr声明,哪个编译器符合C++标准?
问题
以下C++代码在GCC trunk版本中可编译通过:
template <typename T> struct Foo { constexpr void test(); }; void not_constexpr() {} template <> constexpr void Foo<int>::test() { } template <> void Foo<float>::test() { not_constexpr(); } int main() {}
但在Clang和MSVC中编译失败,报错信息如下:
<source>:13:28: error: non-constexpr declaration of 'test' follows constexpr declaration 13 | void Foo<float>::test() { not_constexpr(); } | ^ <source>:4:18: note: previous declaration is here 4 | constexpr void test();
请问哪个编译器的行为符合C++标准?
结论与解释
Clang和MSVC的行为符合C++标准,GCC的处理属于非标准的放宽。
根据C++标准规定,类模板成员函数的特化必须与主模板中的声明保持一致性:主模板中test()被声明为constexpr,那么所有特化版本的test()也必须带有constexpr修饰符——即使特化的实现中调用了非constexpr函数(这种情况下该特化版本实际上无法在常量表达式语境中使用,但语法上仍然必须保留constexpr声明)。
主模板的声明确立了该成员函数的接口契约,特化不能修改这个契约的核心属性(比如是否为constexpr)。GCC允许省略特化的constexpr属于编译器的扩展行为,并不符合标准要求。
内容的提问来源于stack exchange,提问作者user2023370
相关产品推荐
相关产品推荐

