0

ListとSequenceが継承する基本クラスIteratorのLINQスタイルのメソッドを作成しようとしていますが、これら2つのコンテナーにはこれらのメソッドの独自の実装があります。「Where」メソッドは非常に簡単でした。「選択」方法は非常に注意が必要です。仮想テンプレートメソッドを持つことはできません。

  template <typename T>
  class Iterator {
  public:
    virtual ~Iterator() {};

    // This is illegal, but if it weren't, it would be the functionality I want.
    template <typename R>
    virtual shared_ptr<IIterator<R>> Select(const function<R(T)>& func) = 0;

    virtual shared_ptr<IIterator<T>> Where(const function<bool(T)>& func) = 0;
  };

「選択」を使用すると、たとえば、「ハムサンドイッチ」タイプのイテレータを「レタス」タイプのイテレータに変換できます。

HamSandwiches-> Select <'Lettuce'>([](shared_ptr <'HamSandwich'> hs){return hs-> Lettuce;});

一重引用符は無視してください。

仮想テンプレート関数を使用することはできないため、もちろん、関数を仮想化する必要はありません。その場合、単純な古い関数があります。仮想関数と比較して、リストとシーケンスで実装を記述して、その実装を「隠す」ことは絶対にしないでください。設計上の欠陥と見なされます。

  template <typename T>
  class Iterator {
  public:
    virtual ~Iterator() {};

    template <typename R>
    shared_ptr<Iterator<R>> Select(const function<R(T)>& func);

    virtual shared_ptr<Iterator<T>> Where(const function<bool(T)>& func) = 0;
  };

  template <typename T>
  template <typename R>
  shared_ptr<Iterator<R>> Iterator<T>::Select(const function<R(T)>& func) {
    //Implementation - What would it be?
  }

次に、基本クラスに実装を行う必要があります。この実装は、ListとSequenceにある程度固有である必要があります。私が見てきたことから、リストまたはシーケンスによってオーバーライドされる可能性のある「選択」内で特定のアクションを実行するための保護された「実装関数」の作成を開始します。

私はここで正確な答えを探しているのではなく、私がなりたい/なりたい場所にたどり着くのに役立つ何かを探しています。誰かが私が最初に間違っているかもしれない一般的な落とし穴やことを見つけますか?

4

1 に答える 1

3

オプション1

C ++でLINQを実装するために私が見たアイデアは、仮想メソッドにまったく依存していませんでした。代わりに、各結果は、ほぼ次のように、テンプレートクラスにラップされて返されました。

template <class T>
class RangeWrapper
{
public:
    template <class U>
    Select(U u) -> decltype(...) {
        return RangeWrapper<SelectRange, U>(_myRange, u);
    }

private:
    T& _myRange;
};

それらのいくつかをチェーンすると、リターンタイプがかなり大きくなる可能性がありますが、それはコンパイル時にすべてを実行するために支払う代償です。

オプション2

型消去を実装して、常に型のイテレータを返すことができますIterator<T>。これは、Web上の型消去イテレータライブラリを使用して実現するのは非常に簡単です(多くの場合、boost.TypeErasureを確認できますが、これは受け入れられていますが、まだリリースされていません)。または、範囲を操作しても問題がない場合は、ブーストでany_rangeを使用できます(イテレーターよりも自然にLINQにマップされます)。

オプション3

トレーニング演習としてこれを行っていない場合は、すでに実装されているソリューションがいくつかあります。グーグルを使用してください。特に、Microsoft自体がC ++ Linqに取り組んでおり、その上にリアクティブ拡張機能を実装しています。

于 2012-11-19T03:09:24.553 に答える