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にある程度固有である必要があります。私が見てきたことから、リストまたはシーケンスによってオーバーライドされる可能性のある「選択」内で特定のアクションを実行するための保護された「実装関数」の作成を開始します。
私はここで正確な答えを探しているのではなく、私がなりたい/なりたい場所にたどり着くのに役立つ何かを探しています。誰かが私が最初に間違っているかもしれない一般的な落とし穴やことを見つけますか?