2013-03-14 64 views
5

我有一個模板類,它定義了一些成員類型。它類似於std::map基於它自己的模板參數定義它的value_type,但在我的情況下,類型更復雜,所以它被定義爲嵌套類。如何爲成員類型的模板過載免費函數

現在爲了調試,我想爲該類型定義operator<<。但編譯器告訴我它不能推斷出外部模板的模板參數。

我真正的代碼不做作,如下面的例子,但這種人爲的例子證明我想盡了辦法,它是如何失敗的:

#include <iostream> 

template <typename Value> class Outer; 

template <typename Value> 
std::ostream &operator<<(std::ostream &, const typename Outer<Value>::Inner &); 

template <typename Value> 
class Outer { 
    public: 
    struct Inner { 
    Value x; 
    }; 

    void PrintSomething(Value v) { 
    // the real program does something useful with the inner class, of course 
    Inner inner = { v }; 
    std::cout << "Inner = " << inner << std::endl; // <---- THIS SAYS IT CAN'T FIND operator<< 
    }; 
}; 

template <typename Value> 
std::ostream &operator<<(std::ostream &s, const typename Outer<Value>::Inner &v) { 
    return s << v.x; 
} 

int main() { 
    Outer<int> o; 
    o.PrintSomething(42); 
    return 0; 
} 

這是完整的示例重現該問題。編譯器(我已經嘗試了3個)說operator<<沒有超載,它會帶第Outer<int>::Inner類型的第二個參數。當我用不同的函數嘗試同樣的事情時,它沒有其他重載,它代替C2783: could not deduce template argument for 'identifier',gcc和clang一直說不存在第二個參數Outer<int>::Inner)的重載。

那麼,有沒有一種方法來定義operator<<採取Outer<Value>::Inner任何Value,因爲它是正確的(所以它不能被定義爲成員)的說法?

注:我需要它在幾個編譯器中編譯,其中一些沒有任何C++ 11功能,所以我需要它是C++ 03。

+0

使它成爲'Inner'的內聯朋友。 – Xeo 2013-03-14 14:38:21

+0

@Xeo:你能回答嗎?這聽起來是可行的想法。 – 2013-03-14 14:39:25

+0

我不確定你能做到這一點。看到[這個問題](http://stackoverflow.com/questions/9649904/could-not-deduce-template-argument-pointer-to-member),這是接近你的。 – Synxis 2013-03-14 14:41:19

回答

6

你在那裏有一個所謂的不可扣除的上下文Value怎麼可能被推斷?你可以部分地專門化類模板,使得編譯器甚至不可能嘗試和測試每個可能的實例化(其中有...,無限)。

有兩種解決方法:從Outer中取出Inner,或使operator<<成爲內聯好友。後者是人們常用的方式。

template<class T> 
struct Outer{ 
    struct Inner{ 
    T value; 
    friend std::ostream& operator<<(std::ostream& os, Inner const& v){ 
     return os << v.value: 
    } 
    }; 
    // ... 
}; 
+0

我實際上並不直接重載'operator <<',而是一個特定於我的日誌記錄函數的類似函數。對於普通函數,內聯好友隱藏類內的其他重載,包括其內部。所以當我想對內部的東西調用不同的超載時,我不得不使用一點間接性。但這是一個小小的障礙。 – 2013-03-14 14:58:12

相關問題