2011-08-08 40 views
10

有人可以解釋爲什麼這些兩個專業沒有區別的編譯器(gcc 4.5.1 @ ideone)模板偏特

http://ideone.com/9tNux

template <typename... T> struct S; 

template<typename A, typename B, typename... C> 
struct S<A, B, C...> { 
    int f() {return 1;} 
}; 

template<typename... A, typename... C> 
struct S< S<A...>, C...> { 
    int f() {return 2;} 
}; 

,當我嘗試實例S<S<a, b>, a, b> o2;編譯器抱怨:

prog.cpp:20:21: error: ambiguous class template instantiation for 'struct S<S<a, b>, a, b>' 
prog.cpp:6:22: error: candidates are: struct S<A, B, C ...> 
prog.cpp:11:33: error:     struct S<S<A ...>, C ...> 
prog.cpp:20:21: error: aggregate 'S<S<a, b>, a, b> o2' has incomplete type and cannot be defined 

而當最後一個專業化改爲:

template<typename... A, typename B, typename... C> 
struct S< S<A...>, B, C...> { 
    int f() {return 2;} 
} 

一切工作正常。

+0

我想你也可以在這篇文章中添加代碼,因爲它對於這個問題非常重要。 – UncleBens

+0

@UncleBens代碼已添加。 – Predrag

回答

9

我對問題的理解:

typedef S<S<a, b>, c, d> S2; 

這裏S<a,b>第二專業化匹配較好。但是,c, d與第一個專業化的其餘參數(單個arg + list與list)更匹配。因此它是1:1。

如果您在B在第二個特發表評論,那麼第二個專業化匹配更好,因爲它是更專業化的第一個參數(S<...>),其餘都是一樣的好。

+0

很好的解釋,+1!比我做的混亂好多了。 –

+0

容易理解。謝謝! – Predrag

8

我弄糟了這個;它現在應該可以,但信用是由於下面的@UncleBens得到了正確的結果(並且應該得到「接受」)。


如果沒有你的第三個版本的B,你有兩個當實例S<S<X,Y,Z>, T1, T2, T3>兩者同樣特定部分專業:

  • 首先PS:A = S<X,Y,Z>B = T1C... = T2, T3
  • 第二個PS沒有BA... = X,Y,Z,C... = T1, T2, T3
  • 第二個PS與BA... = X,Y,Z,B = T1,C... = T2, T3

這不會在部分特化排序中建立可比較的元素!

請注意,您可以說template <typename ...> struct S;template <typename A, typename ...B> struct S<A, B...>;,第二個比第一個更具體,因爲它具有更多的非可變參數。

但是另一方面,沒有B,當你說S<S<X,Y,Z>,T1,T2,T3>,那麼第一個參數在第二個PS中匹配得更好,但其餘參數在第一個PS中匹配得更好。但是,使用B,第二個PS更具體。

比較這對部分特說其實更具體:

template <typename ...A, typename B, typename ...C> 
struct S<B, std::tuple<C...>, std::tuple<C...>> { /* ... */ }; 

現在很清楚如何是否給定的實例專業化,或者只是一般的格式匹配。專業化擁有固定數量的參數(3),所以它通過可變數量的參數贏得了另一種專業化。

+0

但我的專業不是',B,C ...>和',C ...>'。它們是''和'< S,C ...>'。 – Predrag

+0

這個答案似乎是錯誤的,因爲在你的開放示例中,第二個專業化看起來比第一個更專業。看起來規則是'A'勝過'A ...':在OP的問題中,第二個特化與第一個參數更好地匹配,但第一個特化更好地匹配第二個參數。因此,爲什麼它編譯如果B評論英寸 – UncleBens

+0

@UncleBens:是的,我注意到...一秒鐘,讓我編輯它 –