4

私は現在、とBaseを含むいくつかの仮想メソッドを提供するインターフェイス (次の例) を設計しています。これら 2 つのメソッドは、クラスのような他のコレクションと同様に、対応する反復子を単純に返します。派生クラスはこれらのメソッドを実装し、反復子の特定の実装を返す必要があります。begin()end()

boost::transform_iterator次の (簡略化された) 例は、 を使用して整数のプライベート内部リストを変換する派生クラスを示しています。この実装は、実際には、反復される「もの」が別のものになる可能性があり、イテレータも同様の例にすぎません。

この例は機能しますが、問題が 1 つあります。のオブジェクト型はmain()、使用されたイテレータが型であるという事実を隠しませんTransformIterator。基本クラスは、すべてのプラグインが共有ライブラリであるある種のプラグイン アーキテクチャで使用されます。プラグインは、使用されているイテレータのタイプを認識してはならず、抽象インターフェースのみに依存する必要があります。これを行う方法はありますか?

#include <boost/iterator/transform_iterator.hpp>

#include <iostream>
#include <string>
#include <vector>

template<class Iterator>
class Base
{
public:
    virtual Iterator begin() = 0;
    virtual Iterator end() = 0;
};

struct toString
{
    std::string operator()(int number) const
    {
        return std::to_string(number);
    }
};

typedef boost::transform_iterator<toString, std::vector<int>::iterator> TransformIterator;

class Derived : public Base<TransformIterator>
{
public:
    Derived() : ints{132, 3, 6451, 12, 5} {}

    TransformIterator begin()
    {
        return boost::make_transform_iterator(ints.begin(), toString());
    }

    TransformIterator end()
    {
        return boost::make_transform_iterator(ints.end(), toString());
    }

private:
    std::vector<int> ints;
};

int main()
{
    Base<TransformIterator>* obj = new Derived();
    for(const auto& value : *obj)
    {
        std::cout << value.size() << std::endl;
    }
    return 0;
}

もう少し背景: この特定の例は、構成ファイルを読み取るインターフェイスに基づいています。現在、YAML ファイルの実装のみを計画していますが、XML や古い学校の INI などの他の形式も可能です。したがって、共通のインターフェイス。

4

2 に答える 2

2

古典的な C++ イテレータではありません。それらは多態的な使用を意図していません。

できることは、反復子の抽象基本クラスを定義することです。これは、各具体的な反復子型の (テンプレート化された) ラッパーによって実装されます。抽象基本クラスは、必要なすべての演算子を純粋仮想として定義するだけです。欠点は、イテレータのすべての操作で仮想関数呼び出しが必要になることです...使用状況に応じて、これが問題になる場合とならない場合があります (通常、それらを使用して非常に大きなコレクションを頻繁に反復しない限り、そうではありません)。

例:

template <typename T>
class InputIterator<T>
{
  public:
    virtual T operator*() const = 0;

    // Other operators go here
};

template <typename TIterator>
class ConcreteInputIterator final
:  public InputIterator<typename std::iterator_traits<TIterator>::value_type>
{
  public:
    ConcreteInputIterator(TIterator iterator) : m_iterator(iterator) {}

  public:
    virtual T operator*() const override
    {
      return *m_iterator;
    };

  private:
    TIterator m_iterator;
};
于 2014-03-12T12:01:16.430 に答える