2014-01-30 63 views
0

我不明白。我知道函數模板是邪惡的,但在這種情況下,我們必須使用它。所以這不是問題。我們有一個使用模板運算符函數的存檔。模板函數聲明/定義後物品/穀類型的專業化如下:函數模板重載 - 訂購

class BaseArchive 
{ 
public: 
    BaseArchive() {} 
    virtual ~BaseArchive(); 

    template< typename T > 
    BaseArchive & operator<<(const T &t) 
    { 
     ::operator<<(*this, t); 
     return *this; 
    } 
}; 

BaseArchive & operator<<(BaseArchive &ar, const int & i) 
{ 
    return ar; 
} 

class StdArchive : public BaseArchive 
{ 
public: 
    StdArchive(); 

    template< typename T > 
    StdArchive & operator<<(const T &t) 
    { 
     ::operator<<(*this, t); 
     return *this; 
    } 
}; 

int main() 
{ 
    BaseArchive ar; 
    int i = 7; 
    ar << i; 
} 

在這個例子中,我們得到一個錯誤:

::運算< <尚未聲明

這個可以通過正向聲明來修復

class BaseArchive; 
BaseArchive & operator<<(BaseArchive &ar, const int & i); 

class Archive { ... 

到目前爲止這麼好。但之後一些類爲歸檔定義了它們自己的::運算符,因此很難甚至無法確保特定的運算符聲明總是出現在archive-header-include之前,甚至我們不想使用全局運算符來包含文件。

任何想法如何解決這個和/或解釋爲什麼會出現這個錯誤?像往常一樣,VS編譯soesn't在意這一點,但MinGW的(GCC)編譯器...

千恩萬謝

+0

附註:我建議你的代碼命名空間(避免了全局命名空間) –

+0

當然,我們正在使用的命名空間。這只是一個簡化的coed片段;-) – muffmolch

回答

0

爲什麼沒有獨立的經營者和轉發:

#include<iostream> 

struct BaseArchive {}; 

BaseArchive & operator<<(BaseArchive &ar, const int & i) 
{ 
    std::cout << "BaseArchive\n"; 
    return ar; 
} 

struct StdArchive : BaseArchive {}; 

template< typename T > 
StdArchive& operator<<(StdArchive& archive, const T &t) 
{ 
    std::cout << "StdArchive\n"; 
    operator << (static_cast<BaseArchive&>(archive), t); 
    return archive; 
} 

int main() 
{ 
    StdArchive ar; 
    ar << 7; 
} 
4

首先,函數模板不是邪惡。你從哪裏得到這個想法?

其次,您的設置沒有意義。爲什麼會員功能模板operator <<在那裏?除了向全球版本轉發外,它不做任何事情,並且因爲它使用明確的限定條件,所以ADL不適用。

只需刪除成員函數模板並依靠ADL找到正確的operator<<