2013-04-13 15 views
5
template <typename T> 
class rp { 
}; 

template <template <typename> class P> 
struct b { 
    template <class, template <typename> class FriendP> 
    friend void f(b<FriendP> from); 
}; 

template <class, template <typename> class P> 
void f(b<P> from) { 
} 

int main() { 
    b<rp> v; 
    f<int>(v); 
    return 0; 
} 

Clang 3.3 (svn) biên dịch tốt, trong khi GCC 4.8 từ chối yêu cầu:GCC tuyên bố một hàm bạn để bị quá tải, gọi mơ hồ, kêu vang biên dịch

main.cpp: In function 'int main()': 
main.cpp:17:10: error: call of overloaded 'f(b<rp>&)' is ambiguous 
    f<int>(v); 
     ^
main.cpp:17:10: note: candidates are: 
main.cpp:12:6: note: void f(b<P>) [with <template-parameter-1-1> = int; P = rp] 
void f(b<P> from) { 
    ^
main.cpp:8:17: note: void f(b<FriendP>) [with <template-parameter-2-1> = int; FriendP = rp; P = rp] 
    friend void f(b<FriendP> from); 
       ^

Tôi tự hỏi tại sao GCC tuyên bố f để bị quá tải . Vì vậy, tôi đoán đó là một lỗi GCC.

Trình biên dịch nào là đúng?

+0

'f()' nào gọi clang? –

+0

Vì chỉ định nghĩa '' bên ngoài 'b' có phần thân và không có lỗi liên kết, nên' f' phải được gọi ra. Thực ra chỉ có một 'f'. – hpohl

+0

Tôi muốn nói đây là lỗi GCC. –

Trả lời

1

Tiêm người bạn không còn tồn tại trong tiêu chuẩn C++, hãy xem this để biết thông tin về điều này. Tuy nhiên, vì hàm friend được khai báo bên trong struct b "actions" trên tham số kiểu "b", hàm này được tìm thấy thông qua ADL (tra cứu phụ thuộc đối số). Khi điều này xảy ra, 2 hàm khác nhau có cùng chữ ký được khai báo và trình biên dịch sẽ phàn nàn.

Đây có lẽ là những gì bạn có nghĩa là:

template <template <typename> class P> 
struct b { 
    template <class, template <typename> class FriendP> 
    friend void f(b<FriendP> from){}; 
}; 

nhưng không sử dụng điều này trong mã thực như nó là, kể từ khi "chức năng trùng lặp" vấn đề có thể, như bạn thấy, dễ dàng phát sinh (sử dụng hợp lý không gian tên có thể giúp với sự tôn trọng này).

Mã này có thể được kiểm tra here

Một tài liệu tham khảo tốt cho việc sử dụng (cũng như một ví dụ thực tế cuộc sống tốt đẹp về việc tại sao họ là cần thiết) của hàm friend mẫu có thể được tìm thấy trong mục 46 của hiệu quả C++

+0

Tại sao gcc nghĩ rằng hàm friend có 3 tham số mẫu? –

+0

Vì thực tế có 3: cột đầu tiên là lớp được xác định bởi lớp, lớp thứ hai là FriendP, thứ ba là đối số mẫu của FriendP –

+0

Vấn đề không phải là khả năng hiển thị. Vấn đề là cả hai khai báo 'f' sẽ được xem như khai báo cùng một mẫu hàm. – aschepler