2016-11-20 68 views
3

下面的代码片段是由铛拒绝:异常规范和模板

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主干接受与-std=c++1z的代码。 哪个编译器是正确的?

live example

+0

我假设铿锵工作,如果你添加'noexcept'到'void foo '和'throw()'到'void bar ''? – ildjarn

+0

我的中继gcc拒绝这样的代码。 wandbox也是如此。 – krzaq

回答

2

的铛的解决方法是指定异常规范

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-规范是功能型的一部分,并且可以 显示为任何函数声明的一部分。因为C++ 17

标准的较长版本:(最新草稿)[except.spec/5] ...(重点是我的)。

如果函数的任何声明有异常规范, 不是noexcept规格允许所有的异常,所有 声明,包括定义和任何明确的 专业化,该函数的应具有一个兼容 异常规范。如果任何指向函数的指针声明,对函数的引用或指向成员函数的指针具有异常指定,则所有出现的声明应该具有兼容的异常规范。如果一个函数的声明有一个隐含的异常说明,则函数的其他声明 不应指定异常说明。 在 显式实例中,可以指定异常规范, 但不是必需的。如果在 显式实例化指令中指定了异常规范,则它应该与该函数的其他声明的异常规范兼容。只有在单个翻译单元内的例外规范不是 兼容时,才需要诊断程序 。

+2

好吧,它说:“在一个明确的实例中,可以指定一个异常规范,但不是必需的。”只有在使用和不兼容的情况下,单个CU才需要诊断。 所以它看起来更像是一个叮当虫。 – octoploid

+1

我已经打开https://llvm.org/bugs/show_bug.cgi?id=31081 – octoploid

+0

@octoploid,正确。我修改了我的答案 – WhiZTiM