2017-12-27 21 views
3

Iが仮想メソッドでイテレータネストされたクラスを含む第一のクラスA有する無効な共変戻り型、ネストされたクラスC++

template <typename T > 
class A { 
    public: 
     class iterator { 
     public: 
      virtual ~iterator() {}; 
      virtual T& operator++(); 
     }; 

     virtual iterator begin() const = 0; 
}; 

私は2番目のクラスBを持って、そのオーバーライドvirtualsを方法:

template <typename T > 
class B : public A<T> { 
    public: 
     class iterator : A<T>::iterator { 
      T& operator++() override { 
       iterator p(*this); 
       return p; //for exemple 
      } 
     }; 

    iterator begin() const override { 
     return iterator(this);// for exemple 
    } 
}; 

しかし、私はBクラスを使用する場合:

B<int> test; 

を、私はこのような何かを持っている、コンパイルエラー:

error: invalid covariant return type for 'B<T>::iterator B<T>::begin() const [with T = int]' 
error: overriding 'B<T>::iterator V<T>::begin() const [with T = int]' 

Bクラスのイテレータを実装する方法は?

+1

テクニカルストーリーテラーの話は、(このように呼ばれていた)値型多型と呼ばれ、あなたはこの回答に興味深いリンクを見つけるでしょう:https://stackoverflow.com/questions/38010081/polymorphism-inheritance-and-value-タイプ – Oliv

+1

仮想メソッドは、ポインタと参照でのみ機能します。したがって、イテレータを値で返すことで、それを計画している多態的な動作は無効になります(値による共変な戻りは許されます)。 –

答えて

6

共変種の戻り型は、[class.virtual]/8に従って満たす必要があるいくつかの制約があります。

The return type of an overriding function shall be either identical to the return type of the overridden function or covariant with the classes of the functions. If a function D​::​f overrides a function B​::​f, the return types of the functions are covariant if they satisfy the following criteria:

  • both are pointers to classes, both are lvalue references to classes, or both are rvalue references to classes
  • the class in the return type of B​::​f is the same class as the class in the return type of D​::​f, or is an unambiguous and accessible direct or indirect base class of the class in the return type of D​::​f

  • [...]

あなたのものは一般に継承されないため、ベースにアクセスできません。そして、あなたはポインタや参照を返していません。

値のセマンティクスを持つ型を返すのは良いです!あなたはそれをあきらめるべきではありません。あなたは、共変種戻り型の試みをpimplイディオムで置き換えることができます。 iteratorはポインタを介して多型 "イテレータ実装"クラスを管理します。

関連する問題