2011-06-18 4 views
1

私はvector<Bla> blaVecを宣言し、関数を書く:C++少ない冗長container.startを渡すの代替()とcontainer.end()

template<typename Iterator> 
void doSomething(Iterator first, Iterator last) { ... } 

その後、私はblaVecにこの関数を呼び出す:

doSomething(blaVec.begin(), blaVec.end()); 

しかし、私は本当にdoSomething(blaVec)のような短いものを望んでいますが、関数定義にvectorを指定する必要はありません。基本的には、最初のイテレータだけを指定する良い標準的な方法、あるいはBoost.Rangeによって行われる範囲の[begin、end]イテレータを指定する方法があります。

私はアルゴリズムの男ですから、あまりにも一般的な複雑なソリューションには行きたくありません。私の人生のほとんどは、私はこのような関数を書いた:

void doSomething(vector<int> & bla) { ... } 

しかし、これらの日、私は頻繁に少しより一般的な解決策は、私が一緒に行った理由である、のために呼ばれたのでlistdequevectorで動作doSomethingを書きますイテレータ。しかし、それはあまりにも冗長な解決策であるようです。何を指示してるんですか?

  1. のdoSomething(ベクトル& BLA){...}
  2. doSomethingの(最初のイテレータ、イテレータ最後){...}
  3. のdoSomething(/ *いくつかのレンジデータ構造* /){.. 。}
+0

あなたはBoost.Rangeと言います。遅延評価などの、あらゆる種類の面白い機能も備えています。 –

+0

私はそれがどれほど一般的に使用されているのかよくわかりませんでした。私はソフトウェア設計の面ではなく、アルゴリズムに焦点を当てているので、多くのプログラマーが使用している技術を使用するのが好きです。私はソフトウェアエンジニアリングの最先端にいるのが好きではありません。時折、シンクになることがあります。 –

+1

追加の冗長性は最小限ですが、イテレータ範囲の柔軟性ははるかに優れています。さらに、全範囲をトラバースする必要がある場合は、 'std :: for_each'がそのために設計されています。 –

答えて

11

あなたは、あなたは冗長なこれであることをラップすることができていることが判明した場合:

template<typename Container> 
void doSomething(Container &c) 
{ 
    doSomething(c.begin(), c.end()); //internally call the iterator version. 
} 

そして、この機能を使用し、insteイテレータバージョンの広告。

また、関数をコンテナ内のすべての要素に対して操作したくない場合は、イテレータのバージョンを使用できます。たとえば、

doSomething(c.begin(), c.begin() + 5); //operate on first 5 elements 
             //assuming c.begin()+5 makes sense 
+1

+1。これに関する究極のツールについては、boost :: rangeを参照してください。 boost :: begin/boost :: endを使用すると、Containerをc-arrayや文字列などの任意の型にすることができます。 – Macke

+1

@Macke: 'std :: string'は' begin'と 'end'メンバ関数を持っています。 – Xeo

+1

@ Xeo:私はc-strings(const char *)を参照していました。不明な点がありましたら申し訳ありません。 – Macke

-1

さらに柔軟性が高いため、2番目のものを推奨します。

私はそれが冗長であると感じていませんが、あなたが本当に主張するならば、あなたはそれのためのマクロを定義する場合があります、例えば:

#define FULLITER(a) a.begin(), a.end() 

それはありませんので(念aは簡単な式であることを確認してください)2回実行されます。

+5

Yikes、マクロ:( –

関連する問題