2014-09-19 92 views
3

我想實現operator <<,它將打印模板類的內部類的內容,即X<T>::Y。可以添加任何需要的friend聲明。怎麼做?運算符<<用於模板類的內部類

這裏是什麼,我想在編譯C++ 11一個完​​整的例子:

#include <iostream> 

template <typename T> 
class X { 
public: 
    X(T d): y(d) {} 

private: 
    class Y { 
    public: 
     Y(T d): data(d) {} 

    private: 
     T data; 

     template <typename U> 
     friend std::ostream &operator <<(std::ostream &os, const typename X<U>::Y &y); 
    }; 

    Y y; 

    template <typename U> 
    friend std::ostream &operator <<(std::ostream &os, const X<U> &x); 
}; 

// This operator is not detected by the operator below 
template <typename U> 
std::ostream &operator <<(std::ostream &os, const typename X<U>::Y &y) { 
    os << "Y(" << y.data << ")"; 
    return os; 
} 

template <typename U> 
std::ostream &operator <<(std::ostream &os, const X<U> &x) { 
    os << "X " << x.y; 
    return os; 
} 

int main() { 
    std::cout << X<int>(1); 
    return 0; 
} 

編譯器的錯誤,我得到的是:

error: no match for 'operator<<' (operand types are 'std::basic_ostream<char>' and 'const X<int>::Y') 
os << "X " << x.y; 
      ^
+1

的'U'在'類型名稱X :: Y'是在非推斷上下文。 – 2014-09-19 09:17:33

回答

4

這不起作用,因爲typename X<U>::Y是依賴類型。如果你想打印例如一個int,如果編譯器只是測試所有可能的U(因爲遞歸有很多很多)的類型以便檢查,typename X<U>::Y的結果是否爲int(考慮模板特化!)?因此,唯一的可能性是實施正確的朋友語句的函數:

class Y { 
public: 
    Y(T d): data(d) {} 

private: 
    T data; 

    friend std::ostream &operator <<(std::ostream &os, Y const& y) 
    { 
     os << "Y(" << y.data << ")"; 
     return os; 
    } 
}; 

http://ideone.com/dx8Qri

+0

它的工作原理。爲什麼編譯器不能使用統一來匹配所有定義的'operator <<'? – Xilexio 2014-09-19 09:38:40

+1

我不明白你的意思*統一*。在這種情況下,從'X :: Y'中推導'const' typename X :: Y&'可能在技術上是可行的,但是由於(部分)模板專門化,情況並非總是如此。在以下情況下,編譯器應該如何工作? http://ideone.com/ErCffh – Fytch 2014-09-19 09:53:13

+0

你說得對。它在一般情況下不起作用。 – Xilexio 2014-09-19 09:58:41