0

基本的に、ジェネリック イテレータを含む基本クラスを作成しようとしています。

どうやらテンプレート仮想関数が機能しないため、boost::any を試しましたが、Iterator の get() メソッドをオーバーロードしていません (以下に定義されている Exception をスローし続けます)。また、コンパイラが「仮想反復子 begin() = 0;」について不平を言うため、純粋な仮想にすることもできないようです。(「抽象クラス Iterator のインスタンスを作成できません」と表示されます)。

遵守しなければならない/遵守したい非常に具体的な制約があるため、問題の代替ソリューションが検討される可能性がありますが、おそらく使用できません。

コードの一部を次に示します。

  template <class T, class C>
  class Iterator
  {
    public:
      virtual T& operator*() { T *t = boost::any_cast<T>(&get()); return *t; };
      virtual boost::any& get() { throw new Exception("get not overridden!!"); };
      //virtual boost::any& get() = 0;
    protected:
      C::iterator iter;
  };

  template <class T>
  class VectorIterator: public Iterator<T, std::vector<T> >
  {
    public:
      VectorIterator(std::vector<T>::iterator iterator): Iterator<T, std::vector<T> >(iterator) { };
      virtual boost::any& get() { return *iter; };
  };

  template <class Value, class Container>
  class Repository
  {
    public:
      typedef Iterator<Value, Container> iterator;

      virtual iterator begin() = 0;
      virtual iterator end() = 0;
  };


  class SomeRepository : public Repository<RandomClass, std::vector<RandomClass> >
  {
    public:
      iterator begin() { return VectorIterator<RandomClass>(items.begin()); };

      iterator end() { return VectorIterator<RandomClass>(items.end()); };
  }

では、なぜ機能しないのでしょうか? (どうすれば) 修正できますか?

PS:これは別の質問と非常に似ていることは知っていますが、これをコメントに正確に収めることができず、他にどこに置くことができるか本当にわかりませんでした.

アップデート:

そこで、get() に void (eww) ポインターを返させ、boost::any を忘れることで、なんとか解決しました。しかし、それはまだ VectorIterator::get の代わりに Iterator::get を呼び出します (私の元の問題と同様に) (*someRepository.begin() のようなものを使用しようとすると)、誰かが理由を知っていますか?

4

2 に答える 2

3

type の値から初期化できないのと同じように、 boost::any&fromを初期化することはできません。どちらの場合も、参照する目的のタイプの実際のオブジェクトはありません。*iterfloat&int

getreturn に変更できますboost::any(この場合、からの変換*iterが行われます) が、参照したい (参照型) が関数呼び出しより長く存続する必要がoperator*あるという問題があります。T1 つの解決策は、呼び出しの結果をどこかに保存するか、参照 ( ) ではなく値 ( ) を返すgetようにして、同じ変更をget行うことです。これらは値のセマンティクスであり、基になるコンテナーへの「浅い」ビューではありません。の結果に割り当てても、それが正しいと仮定すると、コンテナの要素には影響しません。operator*TT&operator*

別の可能性は、要素に浅いビューを格納することが保証されているget戻り値を作成することです。boost::any

virtual boost::any get() { return &*iter; }

return boost::ref(*iter);別の可能性です)

operator*次に、期待値を正しく復元するために、内部で注意を払う必要がありますreturn *boost::any_cast<T*>(get());(resp. などreturn boot::any_cast<boost::reference_wrapper<T> >(get()).get();)。これには参照セマンティクスがあり、戻り値T&は問題ありません。の結果に対する操作operator*は、コンテナーの要素に影響を与える可能性があります。

于 2012-10-03T16:21:49.810 に答える
0

'iterator begin()' で Iterator を返す (つまり、値で返す) 場合、戻り値が Iterator に変換されるため、VectorIterator 型ではなくなり、VectorIterator の get メソッドを呼び出さないことは明らかです (少なくとも、私はそうしています)。考える)。参照またはポインターによる戻りは問題なく機能するはずです。

今、私はただ回避策を見つけ出す必要があります。VectorIterator::begin() でローカル変数を返すため、参照渡しは機能しません。他の誰かがより良い提案を持っていない限り、ポインターで戻る必要があると思います。

于 2012-10-04T08:12:33.900 に答える