2012-04-04 23 views
1

ブースト範囲には、簡単に要素を取り込むための組み込みの方法がありますか?たとえば、カンマまたはスペースで区切っていますか?coutブーストの範囲:要素の範囲

私はそれらをループして別々に印刷できることに注意していますが、これは何らかの形で組み込まれているはずです(スクリプト言語でベクターを印刷するなど)。私が見たプログラム例で

、著者はcoutに範囲をコピー:

ブースト::コピー(範囲、ostream_iterator(COUT、 "「))

は私には醜いです。これは慣用的ですか?

EDIT:標準イテレータ用のソリューションも受け入れられます。

EDIT2: は私がやりたいことはこれです:

cout << range; 

しかし、私は作品とは思いません。レンジアダプタと

cout << range.join(", "); 

または多分: だから私は期待しています何この(触発パイソン)のようなものです。

cout << (range | stringify(", ")); 

答えて

4

私は、それが今までに本当に/ポリッシュ仕上げられています信じていませんが、それはBoost.Exploreの意図です。

個人的には、私はちょうどstd::copyの使用に慣れてきました。この種のものについては、infix_ostream_iteratorは時には非常に役に立つことがあります。例えば、このような何か:現状では

#include <vector> 
#include <iostream> 
#include <algorithm> 
#include <iterator> 
#include "infix_iterator.h" 

template <typename T> 
std::ostream& operator<<(std::ostream &o, const std::vector<T>& v) { 
    o << "["; 
    std::copy(v.begin(), v.end(), infix_ostream_iterator<T>(o, ", ")); 
    o << "]"; 
    return o; 
} 

int main() { 

    std::vector<int> x; 

    for (int i=0; i<20; i+=2) 
     x.push_back(i); 

    std::cout << x << "\n"; 
    return 0; 
} 

が、これは、ベクトルを取るoperator<<を持っていますが、それではなく、範囲を取る持っていることは比較的些細なことでしょう。

+0

ありがとうございました。 STLとBoostが共通のコンテナにこれを定義していない理由は何ですか?私はこの方法について知っていたが(しかし、ブースト・エクスプローラについて聞いたことはない)、もっと慣用的な方法があるかもしれないときには、ちょっと汚い定義ヘルパー機能を感じる。 – Gurgeh

+0

@Gurgeh:私は完全にはわかりません。完全に汎用化されていれば、文字列の入力や出力などの問題を「引き継ぐ」可能性があります。 –

+0

それはあまり理由ではありません(もちろん、あなたのせいではありません)。通常の状況下では、オーバーロードされた演算子を正しい順序で解決することは困難ではありません。また、何かが間違っている可能性のあいまいなケースが一度もない場合は、標準コンテナごとに手動で定義することができます。とにかく、何か良いことが数時間で出てこないなら、あなたの答えを選びます。ディスカッションありがとう! – Gurgeh

1

一般的な関数を定義して、繰返し可能な範囲を出力することができます。

template<typename ForwardIter> 
std::string join(const ForwardIter& it1, const ForwardIter& it2, const std::string& separator=" ") { 
    if(it1 != it2) { 
     std::ostringstream s; 
     s << *it1; 
     for(ForwardIter i=it1+1; i!=it2; i++) s << separator << *i; 
     return s.str(); 
    } 
    else return ""; 
} 

template<typename Range> 
std::string join(const Range& r, const std::string& separator=" ") { return join(r.begin(), r.end(), separator); } 

この関数は、文字列を返し、そのような各要素の逆参照を出力することができる等のリスト、ベクトル、セット、など、任意の前進反復可能な範囲を取るべきである:ここで私が使用()関数結合ですostreamによって個別にこの機能により、あなたはそれが好きで使用することができます:

list<int> a = {1,2,3,4}; 
set<int> b = {4,3,2,1}; 
vector<int> c = {1,2,3,4}; 


cout << join(a) << endl; 
cout << join(b, ",") << endl; 
cout << join(c.begin(), c.begin()+2, "~") << endl; 

私はあなたがそのような参加や関節のような名前に名前を変更したい場合がありますので、参加する()名前は、いくつかの名前空間と衝突する可能性があることを覚えておいてください。また、ブーストを使用する場合は、より良い互換性のためにr.begin()の代わりにboost :: begin(r)を使用することもできます。