2016-03-29 21 views
8

下面的代碼:GCC VS與可變參數加上相同類型的額外參數偏特鐺行爲

#include <cstddef> 

template <size_t N, 
      typename T, 
      T first, 
      T... rest> 
struct A { 
}; 

template<typename T, 
     T... args> 
struct A<0, T, args...> { 
}; 

int main() { 
    A<0, int, 1> a0; 
    A<2, int, 1, 2> a2; 
    return 0; 
} 

...不g++5.1.0版本和5.3.0)編譯由於:

error: partial specialization is not more specialized than the primary template because it replaces multiple parameters with a pack expansion

...但是編譯clang

是否允許聲明這種部分專業化?

附註:事實上,專業化是危險的,因爲A<0, int>無法與編譯器(模板參數錯誤編譯)編譯。

+0

要允許'A <0, int>',你必須改變第一個模板。專業化爲時已晚。 – Jarod42

+0

@ Jarod42是的,我知道模板的這種實例化是錯誤的,我只是在'g ++'中引發錯誤,而不是'clang'的T ... args'部分專業化問題(重新組織問題以使它更清晰)。 – Holt

+2

GCC是對的。根據[DR 1495](http://wg21.link/cwg1495),這是不合格的(有點不令人驚訝,因爲它是由GCC的維護者報告的)。 –

回答

8

gcc是正確的,代碼是不合格的,因爲專業化實際上並沒有更專業化。


規則,從[temp.class.spec]是(如DR 1495,H/T TC的所述鏈路的結果):

Within the argument list of a class template partial specialization, the following restrictions apply: [...] The specialization shall be more specialized than the primary template (14.5.5.2).

爲了確定這一點,我們將將其重寫爲合成功能模板:

template <size_t N, class T, T first, T... rest> 
void __f(A<N, T, first, rest...>); // primary 

template <class T, T... args> 
void __f(A<0, T, args...>);   // specialization 

然後再通過部分排序規則。這反過來又涉及爲每個模板參數合成新的類型/值,並查看扣減是否可以在任一方向上成功。

當然,專業化的扣除與主要(由於N vs 0)失敗。在另一個方向上,從[temp.deduct.partial]:

If A was transformed from a function parameter pack and P is not a parameter pack, type deduction fails.

因爲我們正試圖推斷T first對一包,演繹在這個方向也將失敗。這意味着合成的功能模板都不比其他模板更專業化,這意味着類模板專業化並不比主模板更專業化。因此,gcc拒絕是正確的。

0

考慮:

template <class T, T first, T... rest> 
struct X{}; 

template<class T, T... rest> 
struct X<T, rest...>{}; 

完全一樣的錯誤。 因爲first可以解釋爲rest包的第一個元素,所以在這種專業化中沒有區別。如果在專業化中添加first - 那麼這就是主要模板。在你的專業化,雖然你可以添加first

//specialization 
template<typename T, 
     T first, 
     T... args> 
struct A<0, T, first, args...> { 
}; 
相關問題