2009-08-19 35 views
27

Tôi đang cố gắng để nạp chồng toán tử < < như một người bạn để mẫu Pair lớp, nhưng tôi tiếp tục nhận được một cảnh báo trình biên dịch nóiđiều hành bạn quá tải << cho lớp mẫu

friend declaration std::ostream& operator<<(ostream& out, Pair<T,U>& v) declares a non template function 

cho mã này:

friend ostream& operator<<(ostream&, Pair<T,U>&); 

nó mang lại một cảnh báo thứ hai như một đề nghị nói

if this is not what you intended, make sure the function template has already been declared and add <> after the function name here 

Đây là định nghĩa hàm

template <class T, class U> 
ostream& operator<<(ostream& out, Pair<T,U>& v) 
{ 
    out << v.val1 << " " << v.val2; 
} 

và đây là toàn bộ lớp.

template <class T, class U> 
class Pair{ 
public: 
    Pair(T v1, U v2) : val1(v1), val2(v2){} 
    ~Pair(){} 
    Pair& operator=(const Pair&); 
    friend ostream& operator<<(ostream&, Pair<T,U>&); 

private: 
    T val1; 
    U val2; 
}; 

Tôi không chắc chắn nên rút ra gì từ cảnh báo đề xuất, ngoài điều đó có lẽ tôi phải đặt ở đâu đó trong tuyên bố kết bạn. Có ai biết cú pháp thích hợp cho việc này không? Cảm ơn.

Trả lời

19

Bạn khai báo hành < < như trở về một ostream &, nhưng không có câu lệnh return ở tất cả các phương pháp này. Nên là:

template <class T, class U> 
ostream& operator<<(ostream& out, Pair<T,U>& v) 
{ 
    return out << v.val1 << " " << v.val2; 
} 

Ngoài ra, tôi không có vấn đề hay cảnh báo biên dịch mã của bạn trong Visual Studio 2008 với cảnh báo ở cấp 4. Oh, có các mối liên kết lỗi cổ điển, nhưng điều đó có thể dễ dàng bỏ qua bằng cách di chuyển định nghĩa hàm mẫu cho khai báo lớp, như được giải thích trong C++ FAQ.

mã kiểm tra của tôi:

#include <iostream> 
using namespace std; 

template <class T, class U> 
class Pair{ 
public: 
    Pair(T v1, U v2) : val1(v1), val2(v2){} 
    ~Pair(){} 
    Pair& operator=(const Pair&); 
    friend ostream& operator<<(ostream& out, Pair<T,U>& v) 
    { 
     return out << v.val1 << " " << v.val2; 
    } 
private:  
    T val1; 
    U val2; 
}; 

int main() { 
    Pair<int, int> a(3, 4); 
    cout << a;  
} 
44

Bạn muốn tạo một cá thể đơn lẻ (được gọi là "chuyên môn hóa" trong các thuật ngữ chung) của mẫu đó là bạn bè. Bạn làm điều đó theo cách sau

template <class T, class U> 
class Pair{ 
public: 
    Pair(T v1, U v2) : val1(v1), val2(v2){} 
    ~Pair(){} 
    Pair& operator=(const Pair&); 
    friend ostream& operator<< <> (ostream&, Pair<T,U>&); 

private: 
    T val1; 
    U val2; 
}; 

Bởi vì trình biên dịch biết từ danh sách tham số mà các đối số mẫu là TU, bạn không cần phải đưa những giữa <...>, vì vậy họ có thể để trống. Lưu ý rằng bạn cần phải đặt một tuyên bố operator<< trên Pair mẫu, như sau:

template <class T, class U> class Pair; 

template <class T, class U> 
ostream& operator<<(ostream& out, Pair<T,U>& v); 

// now the Pair template definition... 
+9

+1 này thực sự là những gì các trình biên dịch được khiếu nại. Câu trả lời khác đề cập đến vấn đề với cách giải quyết: thay vì nói với trình biên dịch rằng người bạn là chuyên môn hóa của khuôn mẫu nó tạo ra một hàm << toán tử không được lập biểu mẫu cho các kiểu đã cho. –

+0

Tôi đồng ý với David; đây là giải pháp tốt nhất về mặt thực hành tốt nhất và lập trình tốt. – Andry

+1

Wow, phần bổ sung '<>' rất dễ bỏ lỡ! – Nick

1

Simple phiên bản inline:

template<typename T> class HasFriend { 
    private: 
     T item; 
    public: 
     ~HasFriend() {} 
     HasFriend(const T &i) : item(i) {} 
    friend ostream& operator<<(ostream& os, const HasFriend<T>& x) { 
     return os << "s(" << sizeof(x) << ").op<<" << x.item << endl; 
    } 
}; 

Revised mẫu phiên bản:

template<template<typename /**/> class U, typename V> 
ostream& operator<<(ostream &os, const U<V> &x) { 
    return os << "s(" << sizeof(x) << ").op<<" << x.item << endl; 
} 

template<typename T> class HasFriend { 
    private: 
     T item; 
    public: 
     ~HasFriend() {} 
     HasFriend(const T &i) : item(i) {} 
    friend ostream& operator<<<>(ostream&, const HasFriend<T>&); 
}; 
Các vấn đề liên quan