例外规范和模板

时间:2016-11-20 21:01:27

标签: c++ c++17

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

1 个答案:

答案 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有一个隐式异常规范,其他声明   该函数不应指定异常规范。 在一个   显式实例化可以指定异常规范,   但不是必需的。如果在。中指定了异常规范   显式实例化指令,它应该与   异常 - 该函数的其他声明的规范。一个   仅当异常规范不是时才需要诊断   在单个翻译单元中兼容。