clang拒绝以下代码段:
template <typename T> void foo() noexcept {}
template <typename T> void bar() throw() {}
template void foo<int>();
template void bar<int>();
clang++ -std=c++1z -c
我得到:
compat.ii:3:15: error: explicit instantiation of 'foo' does not refer to a function template, variable template, member function, member class, or static data member
template void foo<int>();
^
compat.ii:1:28: note: candidate template ignored: could not match 'void () noexcept' against 'void ()'
template <typename T> void foo() noexcept {}
^
compat.ii:4:15: error: explicit instantiation of 'bar' does not refer to a function template, variable template, member function, member class, or static data member
template void bar<int>();
^
compat.ii:2:28: note: candidate template ignored: could not match 'void () throw()' against 'void ()'
template <typename T> void bar() throw() {}
^
2 errors generated.
gcc trunk接受-std=c++1z
的代码。
哪个编译器是对的?
答案 0 :(得分:2)
Clang的解决方法是指定例外 spec :
template <typename T> void foo() noexcept {}
template <typename T> void bar() throw() {}
template void foo<int>() noexcept;
template void bar<int>() throw();
尽管从C ++ 17开始,异常规范现在是函数签名的一部分,但它不是显式实例化所必需的。引用Cppreference:
noexcept-specification是函数类型的一部分,可以 作为任何函数声明符的一部分出现。自C ++ 17
标准的较长版本:(最新草稿)[except.spec/5] ...(强调我的)。
如果函数的任何声明都有异常规范 不是允许所有异常的noexcept规范 声明,包括定义和任何明确的 专业化,该功能应具有兼容性 异常规范。如果有任何指向函数的声明, 引用函数,或指向成员函数的指针有一个 例外规范,该声明的所有出现均应 有一个兼容的异常规范。如果声明了 function有一个隐式异常规范,其他声明 该函数不应指定异常规范。 在一个 显式实例化可以指定异常规范, 但不是必需的。如果在。中指定了异常规范 显式实例化指令,它应该与 异常 - 该函数的其他声明的规范。一个 仅当异常规范不是时才需要诊断 在单个翻译单元中兼容。