2011-09-16 52 views
6

我試圖做這種方式:如何重載operator <<用於C++中的數組?

template <typename T> 
ostream &operator<<(ostream &os, T &arr) 
{ /*...*/ } 

但可以T表示數組?爲數組過載<<運算符是否正確?


編輯:

根據Kerrek SB的建議,這裏是我的<<實現:

template <typename T, unsigned int N> 
ostream &operator<<(ostream &os, const T (&arr)[N]) 
{ 
    int i; 
    for(i = 0; i < N; i++) 
     os << arr[i] << " "; 
    os << endl; 
    return os; 
} 

是我實現嗎?我收到了編譯錯誤。

回答

7

你可以這樣做:

template <typename T, unsigned int N> 
std::ostream & operator<<(std::ostream & os, const T (&arr)[N]) 
{ 
    // .. 
    return os; 
} 

這僅適用於編譯時的陣列,當然。請注意,當T是內置類型或std名稱空間中的類型時,不允許您實例化此模板!

如果可能,可能最好使它內聯,因爲每個N都會導致單獨實例化。 (該pretty printer有這樣的一個例子。)

你會發現,雖然,毯子模板帶來了模棱兩可的,因爲os << "Hello"現在有兩個可能的過載:模板匹配const char (&)[6],和(非模板)過載衰減到指針const char *,它們都具有相同的轉換序列。我們可以通過禁用我們的字符數組超載解決此問題:

#include <ostream> 
#include <type_traits> 

template <typename T, unsigned int N> 
typename std::enable_if<!std::is_same<T, char>::value, std::ostream &>::type 
operator<<(std::ostream & os, const T (&arr)[N]) 
{ 
    // .. 
    return os; 
} 

事實上,會更加普遍,你還可以使basic_ostream參數模板參數:

template <typename T, unsigned int N, typename CTy, typename CTr> 
typename std::enable_if<!std::is_same<T, char>::value, 
         std::basic_ostream<CTy, CTr> &>::type 
operator<<(std::basic_ostream<CTy, CTr> & os, const T (&arr)[N]) 
{ 
    // .. 
    return os; 
} 

鑑於事實T必須是用戶定義的類型,您甚至可以用is_fundamental<T>替換is_same<T, char>以獲得更多檢查(但用戶仍然不能將其用於標準庫類型的數組)。

+0

謝謝,不過我還是要說不明白爲什麼它會導致每個N單獨實例化,如果沒有實現內聯? – Alcott

+0

嗯,它是一個模板,所以每個模板實例最終都可以作爲二進制文件中的一個獨立函數。如果你內聯,你可以完全避免函數調用,儘管這最終取決於編譯器。 –

+0

明白了。用這個運算符<<有2個模板參數,我怎樣才能指定第二個參數N?顯然,我不能僅僅使用「cout << ar;」,我可以嗎? – Alcott

3

另一種方法可以做到這一點會是像下面這樣:

template<typename T> 
ostream& operator<<(ostream &out, const std::pair<T, int>& array) 
{ 
    //...code 
    return out; 
} 

T將採取一個指向數組的指針(即,它將是指針類型的數組會衰變成) ,並且該對中的int部分將是該數組的大小。然後,您可以使用它像下面這樣:用這種方法

int array[10]; 
//...some code that initializes array, etc. 

cout << make_pair(array, 10); 

一加是它也將動態數組工作(即陣列您在堆上分配等)

+0

我會試試看。謝謝 – Alcott

+0

我有一種很微弱的感覺,如果你的'T'不是用戶定義的類型,那麼你可能在ADL遇到麻煩,儘管我不能確定。 –

+0

我用'int'等內建類型測試過它......似乎工作得很好......我想不出爲什麼這會與ADL規則相沖突。如果你有一個'std :: pair '對象,模板應該能夠推導出類型'T',並且拒絕使用'std :: pair '的任何實例,其中'U'不是'int'類型的' 。 – Jason