0

私は過去 6 年間、ほぼ独占的に C# プログラマーでした。私は現在、C++ が最適な言語であり、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 の代わりに列挙子間の比較を使用するため、列挙子の最終値を決定する必要があります。次に、すべての iterator_traits ナンセンスを台無しにする必要があります。STL は実行時の動的ディスパッチではなく、コンパイル時のテンプレート ディスパッチを使用するため、入力列挙子の value_type だけでなく、特定の種類の入力列挙子についても反復子をテンプレート化する必要があります。

STL で map-join イテレータを書こうとしたときから始めないでください。

他の人が書いたコードを見て、Boost で拡張されていない STL は、コレクションとソート以外にはめったに使用されないという結論に達しました。

私の近位観察は次のとおりです。

  1. STLで突然変異イテレータを簡潔に書く方法はありますか?
  2. あるコレクションを別のコレクションに簡潔に並べ替えるにはどうすればよいでしょうか?

より一般的には、私の慣れ親しんだ考え方と衝突するいくつかのことに気付きました。

  1. STL コードは簡潔ではないようです。簡潔なコードを書くという私の目的は、STL コードを書くときに問題になりますか? (簡潔ではないということは、つまり、非常に長い型識別子が含まれることが多いということです)
  2. ブーストは、STL でアルゴリズムを記述するためのほぼ必須のようです。Boost の使用を許可されていない人は何をしますか?
4

1 に答える 1

2

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

iterator_traits少なくとも存在しますが、それらは私が「台無しにする」ことはめったにありません。私はそれらの存在を周辺的に認識していますが、それ以上のものはほとんどありません. 私はかなりの数のイテレータとアルゴリズムを書いてきましたが、具体的なことは何もしiterator_traitsていません。

別のコレクションのソートされたバージョンである新しいコレクションを作成するという特定の問題に取り掛かりましょう。これは、さまざまな方法でかなり簡単です。 std::partial_sort_copy確かにそれを行うことができます:

#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::vector<int> result(input.begin(), input.end());
std::sort(result.begin(), result.end());

本当に簡潔にしたい場合は、本質的にソートされたデータ構造にコピーを作成できます。

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

ただし、これは通常、コードを短くするために少し効率を犠牲にします。多くの (ほとんどの?) 状況では、これは問題ではありませんが、遅すぎると感じた場合は、より高速な代替手段を簡単に利用できます。

于 2012-04-04T19:38:20.917 に答える