异常规范和模板

Exception specifications and templates

以下代码段被 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 的代码。 哪个编译器是正确的?

live example

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:

The noexcept-specification is a part of the function type and may appear as part of any function declarator. since C++17

标准的较长版本:(最新草案)[except.spec/5] ...(强调我的)。

If any declaration of a function has an exception-specification that is not a noexcept-specification allowing all exceptions, all declarations, including the definition and any explicit specialization, of that function shall have a compatible exception-specification. If any declaration of a pointer to function, reference to function, or pointer to member function has an exception-specification, all occurrences of that declaration shall have a compatible exception-specification. If a declaration of a function has an implicit exception specification, other declarations of the function shall not specify an exception-specification. In an explicit instantiation an exception-specification may be specified, but is not required. If an exception-specification is specified in an explicit instantiation directive, it shall be compatible with the exception-specifications of other declarations of that function. A diagnostic is required only if the exception-specifications are not compatible within a single translation unit.