2016-03-07 96 views
3

下面的示例是我遇到的模板問題的蒸餾版本 - 請參閱下面的編譯錯誤。如何重載operator <<以輸出在模板內定義的向量?

#include <iostream> 
#include <vector> 

template <class T> struct S 
{ 
    typedef std::vector<T> SVec; 
}; 

template <class T> std::ostream& operator<<(std::ostream& OS, const S<T>::SVec& X) 
{ 
    for (const auto& e: X) OS << e << ' '; 
    return OS; 
} 

int main() 
{ 
    S<int>::SVec v; 
    std::cout << v << std::endl; 
} 

編譯器輸出:

g++ -g -Wall -O4 -std=c++11 -c tc041.cpp 
tc041.cpp:22:69: error: need ‘typename’ before ‘S<T>::SVec’ because ‘S<T>’ is a dependent scope 
template <class T> std::ostream& operator<<(std::ostream& OS, const S<T>::SVec& X) 

等等 - 數百行。 我的編譯器 - g ++ 5.2.1,OS - Xubuntu 4.2.0。

如何使該運算符能夠正確編譯?

+0

錯誤消息其實是非常字面,儘管它需要一些更多的知識去了解它。 –

回答

3

有兩個問題:

  • 在缺少運算符聲明typename關鍵字。
  • 模板類型扣除在main中失敗。

template <class T> 
std::ostream& operator<<(std::ostream& OS, const typename S<T>::SVec& X) 

typename關鍵字應S<T>::SVec之前。由於語言規則,編譯器不知道SVec是否是成員類型或其他。 typename關鍵字是告訴編譯器它是一個類型。

有關的語言規則的詳細信息,可參考:http://en.cppreference.com/w/cpp/language/dependent_name


(注:我其實它不太確定,因爲這個場景是我新太)

讓我們做一個實驗。我們不用函數語法調用operator<<,而是用函數語法調用它。

operator<< (std::cout, v); 

那麼,它仍然失敗。

如果我們用顯式模板參數調用它會怎樣?

operator<< <int> (std::cout, v); 

它的工作原理!那麼,實際上,可能會工作。我發現一些標準庫頭可能包含干擾它的內容。但讓我們把它放在一邊。

本實驗演示的問題是模板參數推演失敗。無法推導出形式爲class-template-name<T>::member-type的參數類型。

詳情:http://en.cppreference.com/w/cpp/language/template_argument_deduction

+0

謝謝,它有幫助。有什麼方法可以「幫助」編譯器推斷出這個論點? – HEKTO

+0

@HEKTO我沒有一個好的解決方案。你可以考慮使用'std :: vector '或'S '。 –