2016-11-20 67 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