2011-09-16 16 views
6

私は、このようにそれをやろうとしている:C++の配列の演算子<<をオーバーロードする方法は?

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

しかしT配列を表すことができますか?アレイのために<<演算子をオーバーロードするのは正しいですか?


EDIT:

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"は現在2つの可能なオーバーロードが持っているのであなたは、毛布のテンプレートは、あいまいさを紹介していること、しかし、気づくでしょう

const char (&)[6]テンプレートマッチング、および(非テンプレート)を過負荷のために両方とも同一の変換シーケンスを有する崩壊対ポインタconst char *である。事実を考慮して

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; 
} 

#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パラメータテンプレートパラメータを作ることができ、より一般的なこと:私たちは、char配列のための私達のオーバーロードを無効にすることでこの問題を解決することができますTはユーザー定義の型でなければなりません。is_same<T, char>is_fundamental<T>に置き換えることで、さらに多くのチェックを行うことができます(ユーザーは標準ライブラリタイプの配列に対してこれを使用してはいけません)。

+0

感謝を(あなたがなど、ヒープ上に割り当て、すなわち配列)が、私ドン、それはまた、動的配列のために動作します。この方法では

int array[10]; //...some code that initializes array, etc. cout << make_pair(array, 10); 

ワンプラス:あなたは、次のようにそれを使用することができますインラインで実装されていない場合、Nごとに個別のインスタンス化を引き起こす理由を理解できませんか? – Alcott

+0

まあ、それはテンプレートなので、すべてのテンプレートインスタンスはバイナリの別の関数として終わることがあります。インライン化すると、関数呼び出しを完全に回避することができますが、これは最終的にはコンパイラによるものです。 –

+0

がそれを手に入れました。この演算子<< 2つのテンプレート引数を持つと、どのようにして2番目のarg Nを指定できますか?どうやら、私は単純に "cout << ar;"を使うことはできないのですか? – Alcott

3

あなたは、これは以下のようなものになるだろう行うことができます別の方法:Tは、配列へのポインタを取ります

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

(すなわち、配列がに崩壊することをポインタ型になります)ペアのint部分は配列のサイズになります。

+0

私はそれを試してみましょう。ありがとう – Alcott

+0

あなたの 'T 'がユーザ定義の型でない場合は、ここでADLの問題に遭うかもしれないという非常にかすかな気持ちがあります。 –

+0

私は 'int'のようなビルドイン型でテストしました...うまく動いていたようです...なぜこれがADLの規則と矛盾するのだろうとは思いません。 'std :: pair 'オブジェクトを持っている場合、テンプレートは 'T'型を推論し、' std :: pair ''を使ってインスタンス化を拒否することができます。 'U'型は' int'型ではありません。 – Jason

関連する問題