2017-01-17 17 views
0

私は「モダンな」C++を特にテンプレートを使ってスピードアップしようとしています。 < <演算子を上書きするクラスポイントがあります。正常に動作します。だから、私は一般的な容器のために素敵なプリントを追加することにしました。一般化された(テンプレート)コンテナのアウトパターを書く方法

私の質問 - 以下のコードのような複数のコンテナタイプのテンプレートを書く方法はありますか?

template <typename T> 
std::ostream& operator <<(ostream& os, const vector<T>& v) 
{ 
    os << "\n"; 
    for(auto x : v) { os << "\n\t" << x; } 
    os << "\n"; 
    return os; 
} 

上記のコードは正確であればTは< <オペレータを有するようなマルチライン形式のベクトルを出力します。

また、すべてのタイプの一般的な方法でコンテナの出力をオーバーライドすることは、おそらく悪い考えです(少なくとも無礼です)。最終的に、上記のテンプレートコードはtypenameをハードコーディング/「Point」とテンプレート付きコンテナに限定しています。 AndyGの提案をimplimenting OK


、私は以下の完全なコードがあります。まだ

#include <iostream> 
#include <map> 
#include <vector> 

using namespace std; 


struct Point { 
    double x, y, z; 

    Point() : x(0), y(0), z(0) {}; 
    Point(double a, double b, double c) : x(a), y(b), z(c) {} 
    Point(double a[]) : x(a[0]), y(a[0]), z(a[0]) {} 

    friend std::ostream& operator <<(ostream& os, const Point&p) 
    { 
    os << p.x << ", " << p.y << ", "<< p.z; 
    return os; 
    } 

}; 

template <template<class> class C, class... T> 
std::ostream& operator <<(ostream& os, const C<T...>& v) 
{ 
    os << "\n"; 
    for(auto x : v) { os << "\n\t" << x; } 
    os << "\n"; 
    return os; 
} 

vector<Point> vp = { { 1, 2, 3 }, 
        { 5, 7, 4 }, 
        { 8, 2, 5 } 
}; 

int main(int argc, char* argv[]) 
{ 
    cout << vp[0]; // works 
    cout << vp; // dosen't work, 
} 

しかし、運を。コンパイラは、私が同じ結果についてで私の最初のポストにtemplate <template>前の多くのバリエーションを試してみました

「のstd ::ベクトル」でオペレータ< <と一致することはできません。私はコンパイルするテンプレートを得ることができますが、コンパイラは演算子関数と一致してテンプレートを使用しません。

私はvariadicテンプレートパックを認識していませんでしたが、明らかに良いアイデアですが、問題を解決しません。

+0

'テンプレート<テンプレートクラスC、クラス... T> のstd :: ostreamに&演算子<<(ostreamに&OS、constのC &V):

このリンクは、きちんとしたコンテナかわいいプリントLIBを持っていますしかし、あなたは間違いなくいくつかの問題を抱えています。 'std :: map'のような連想型コンテナは、' std :: vector'のような非連想型のものと一括して扱いにくいものです。 – AndyG

+1

同様の作業がここに記述されています:http://stackoverflow.com/questions/4850473/pretty-print- c-stl-containers –

+0

あなたが言うように、私のタイプを含む**すべての** Tに一致するテンプレートを追加するのは非常に失礼です。それが 'std :: vector'がまだ持っていない理由の1つです。 –

答えて

0

OK、AndyGが私を正しい軌道に乗せ、何が起きているのか分かりました。

std :: containerテンプレートにも既定値を持つallocatorパラメータがあり、めったに使用する必要がないため、次のコードは機能しません。したがって、ほとんどのコンテナテンプレートは、含まれる型/クラスのみをとっていると考えています。

この

template < template <class> class C, class... T> 
std::ostream& operator <<(ostream& os, const C<T...>& v) 
{ ... } 

動作しません。私たちは私たちのオペレータに< <機能をCを呼び出すしようとしているテンプレートは、2つのパラメータではないものを取るため。したがって、コンパイラは一致を検出しません。

これは動作します:コンパイラは、我々はCを呼び出すことを選択しtemplate<class, class>からvector<Point, Alloc>を一致させることができます

template < template <class, class> class C, class... T> 
std::ostream& operator <<(ostream& os, const C<T...>& v) 

ので。その後、関数テンプレートを使用してoperator <<のオーバーロードを生成することができます。

このアプローチには多くの問題があることに注意してください。 template <class, class>は4つのパラメータを取るstd :: mapと一致しません。そのうち2つはデフォルトに設定されています。 と一致しますコンテナであってもなくてもよい2つの引数テンプレート。

我々はVARGパラメータを使用してこの問題を解決することができます。template <class, class...>しかし、我々はまだ今< <関数テンプレートは、コンパイラがどのようにcout <<を知らないイテレータからstd::pairsを扱っているので、ネジ止めされます

これは、私がテンプレートをよりよく理解するのに便利な演習でしたが、しないでください。 Pretty-print C++ STL containers

+0

私は元のコメントに 'template class C、class ... T>'と言っていたのですが、残念です。 – AndyG

+0

NP - あなたの答えがうまくいかなかった理由を理解する努力(私にとって)が価値がありました。ありがとう。 – DBB

関連する問題