2011-08-08 40 views
10

ai đó có thể giải thích tại sao hai chuyên ngành không thể phân biệt với các trình biên dịch (gcc 4.5.1 @ ideone)Template phần chuyên môn hóa

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;} 
}; 

và khi tôi cố gắng để nhanh chóng S<S<a, b>, a, b> o2; biên dịch phàn nàn:

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 

Và khi chuyên môn cuối cùng được đổi thành:

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

mọi thứ hoạt động tốt.

+0

Tôi nghĩ bạn cũng có thể thêm mã trong bài đăng này vì điều này rất quan trọng đối với câu hỏi. Đã thêm – UncleBens

+0

@UncleBens Code. – Predrag

Trả lời

9

hiểu biết của tôi về vấn đề này:

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

Đây S<a,b> phù hợp với chuyên môn thứ hai tốt hơn. Tuy nhiên, c, d là một kết hợp tốt hơn cho các đối số còn lại của chuyên môn đầu tiên (danh sách arg + danh sách vs). Do đó nó là 1: 1.

Nếu bạn bình luận trong B trong chuyên môn thứ hai, thì chuyên môn thứ hai phù hợp hơn vì nó chuyên môn hơn cho đối số đầu tiên (S<...>) và phần còn lại đều tốt.

+0

Giải thích hay, +1! Tốt hơn nhiều so với mớ hỗn độn mà tôi tạo ra. –

+0

Dễ hiểu. Cảm ơn bạn! – Predrag

8

Tôi đã làm một mớ hỗn độn này; nó sẽ được OK ngay bây giờ, nhưng tín dụng là do @ UncleBens dưới đây người đã nhận nó đúng (và sẽ nhận được "chấp nhận").


Nếu không có sự B trong phiên bản thứ ba của bạn, bạn có hai chuyên ngành một phần là như nhau cụ thể khi bạn nhanh chóng S<S<X,Y,Z>, T1, T2, T3>:

  • Đầu PS: A = S<X,Y,Z>, B = T1, C... = T2, T3.
  • PS thứ hai mà không cần B: A... = X,Y,Z, C... = T1, T2, T3.
  • PS thứ hai với B: A... = X,Y,Z, B = T1, C... = T2, T3.

Điều này không thiết lập các yếu tố có thể so sánh theo thứ tự chuyên môn hóa từng phần!

Lưu ý rằng bạn có thể nói template <typename ...> struct S;template <typename A, typename ...B> struct S<A, B...>; và cái thứ hai cụ thể hơn so với số đầu tiên bởi vì nó có nhiều thông số phi-variadic hơn.

Nhưng mặt khác, nếu không có B, khi bạn nói S<S<X,Y,Z>,T1,T2,T3>, thì đối số đầu tiên phù hợp tốt hơn trong PS thứ hai, nhưng các đối số còn lại phù hợp tốt hơn trong PS đầu tiên. Tuy nhiên, với số B, PS thứ hai cụ thể hơn.

Hãy so sánh này đến chuyên môn hóa từng phần mà thực sự cụ thể hơn:

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

Bây giờ nó là rõ ràng như thế nào cho dù một ví dụ cho phù hợp với chuyên môn, hoặc chỉ có hình thức nói chung. Chuyên môn có một số cố định các tham số (3), do đó, nó thắng hơn một chuyên môn khác với một số biến đối số.

+0

Nhưng chuyên môn của tôi không phải là ', B, C ...> 'và' , C ...> '. Chúng là '' và '< S, C ...>'. – Predrag

+0

Câu trả lời này có vẻ sai, bởi vì trong ví dụ mở đầu của bạn, chuyên môn thứ hai có vẻ chuyên biệt hơn so với lần đầu tiên. Có vẻ như quy tắc là 'A' trumps 'A ...': trong câu hỏi của OP, chuyên môn thứ hai khớp với đối số đầu tiên tốt hơn, nhưng chuyên môn đầu tiên khớp với đối số thứ hai tốt hơn. Do đó, tại sao nó biên dịch nếu B được nhận xét. – UncleBens

+0

@UncleBens: Vâng, tôi nhận thấy ... một giây, hãy để tôi chỉnh sửa nó –

Các vấn đề liên quan