2012-04-04 7 views
1

私は過去6年間ほとんど独占的にC#プログラマーでした。私は現在、C++が選択された言語であり、STLはコレクションのライブラリです。STLのフレームを採用するためのヒント

C#のLINQを使用した後、私はSTLフレームに入るのが非常に困難です。

例として:IEnumerator.Selectに相当するものを作成します。

C#

public static IEnumerator<Output> Select(this IEnumerator<Input> input, Func<Input, Output> func) { 
    while (input.MoveNext) { 
    yield return func(input.Current); 
    } 
} 

超簡単。

ここで、C++とSTLで同様のことを試してみてください。 (yieldキーワードと匿名関数の便利な構文の問題を除いて)。

多くの難しい質問にはじめて答える必要はありません。 STL列挙子はMoveNextではなく列挙子間の比較を使用するため、列挙子の終端値を決定する必要があります。それからあなたはイテレーターのすべてのナンセンスを混乱させる必要があります。 STLは実行時の動的ディスパッチの代わりにコンパイル時のテンプレートディスパッチを使用するため、イテレータは入力列挙子のvalue_typeだけでなく、特定の種類の入力列挙子にテンプレート化する必要があります。

STLでマップ結合イテレータを書き込もうとしていました。

他の人が書いたコードを見ると、Boostで拡張されていないSTLは、コレクションやソート以外のものではほとんど使用されないという結論に至りました。

私の近位の観測は以下のとおりです。

  1. 簡潔STLの変異イテレータを書くための方法はありますか?
  2. 1つのコレクションを他のコレクションに簡潔にソートコピーしますか?

    1. STLコードが簡潔ではないようです:

    は、より一般的に、私は思考の私の慣れた方法と衝突するいくつかのことを気づきました。 STLコードを書くときに、簡潔なコードに責任を負うことを私の目的はしていますか? (簡潔ではないので、しばしば非常に長い型の識別子が含まれます)

  3. ブーストはSTLでアルゴリズムを書くのに近い要件のようです。 Boostの使用を許可されていない人はどうしますか?
+0

いいえ、ストリームは壊れていますが、残りは正常です。 BoostとQTはどちらも、STLをはるかに大きなフレームワークに拡張します。一般的な拡張機能としてBoost、GUI関連のものについてはQTです。 'IEnumerator.Select'が正しく理解されていれば、' boost :: transform_iterator'を呼び出します。私が 'boost :: zip_iterator'を理解していれば、それはあなたのマップ結合反復子です。 –

+0

私のプロジェクト要件はBoostを禁じていることに注意してください。 –

+0

あなたは ''ヘッダが何を提供しているのかを見てください。 – Attila

答えて

2

あなたの質問のいくつかは、本当に私には分かりません。たとえば、 "enumerator_traits"に対処する必要があると話します。あなたが何を話しているのかよく分かりません。たぶんあなたはiterator_traitsを意味するでしょうか?私は "enumerator_trait"と呼ばれるものを使用したことを思い出していませんし、C++標準でそのようなことについて言及することもできません。

iterator_traits少なくとも存在しますが、私はめったに「混乱して」います。私は彼らの存在を周縁的に認識していますが、それ以上のことはありません。私はイテレータとアルゴリズムのかなりの数を書いてきましたが、そのうちのどれでもiterator_traitsで特定のことを行うことはありません。

別のコレクションのソート済みバージョンである新しいコレクションを作成する具体的な質問に行きましょう。これはさまざまな方法でかなり簡単です。あなたは本当にそれが簡潔たい場合は、あなたにコピーを作成することができます

std::vector<int> result(input.begin(), input.end()); 
std::sort(result.begin(), result.end()); 

:多くの目的のために

#include <algorithm> 
#include <vector> 
#include <iterator> 
#include <iostream> 

int main() { 

    std::vector<int> input; 

    // generate some data to sort 
    std::generate_n(std::back_inserter(input), 20, rand); 

    // a destination for the sorted data: 
    std::vector<int> result(input.size()); 

    // do the sort/copy: 
    std::partial_sort_copy(input.begin(), input.end(), 
     result.begin(), result.end()); 

    // show the sorted data: 
    std::copy(result.begin(), result.end(), 
     std::ostream_iterator<int>(std::cout, "\n")); 

    return 0; 
} 

が、しかし、それはその後、ソート、コピーを作成する方が簡単です:std::partial_sort_copyは確かにそれを行うことができます

この最後のコードは、通常、コードを短くするために少し効率的です。多くの(ほとんどの場合)状況下では問題はありませんが、それが遅すぎると、より早い選択肢が容易に利用できます。

+0

ここでは、1つのコピーだけの並べ替えがあります:http://ideone.com/s7IjE。 21行。私が入力した最も長い識別子は 'std :: vector 'でした。 –

+0

とトランスフォームイテレータ:http://ideone.com/PYyvY。 26行。もっと複雑な、それほど悪くない。通常のことは、Jerryが言っているように、一度に 'std :: transform'だけです。 –

+0

@Mooing Duckトランスフォームイテレータの実装には、重要ではない、一般に適用可能な啓示があります。エンドポイントイテレータでmake_transformを呼び出すことは、LINQプログラマにとっては明白ではなく、良いアプローチのようです。 –