14

独自のコンテナクラスを作成していますが、頭を悩ませることができない問題が発生しました。これが問題を示す最低限のサンプルです。

これは、コンテナークラスと2つのテストクラスで構成されます。1つはstd:vectorを使用するテストクラスで、2つ目は、まったく同じ方法で独自のコンテナークラスを使用しようとしますが、コンパイルに失敗します。

#include <vector>
#include <algorithm>
#include <iterator>

using namespace std;

template <typename T>
class MyContainer
{
public:
  
  class iterator
  {
  public:
    typedef iterator self_type;
    inline iterator() { }
  };

  class const_iterator
  {
  public:
    typedef const_iterator self_type;
    inline const_iterator() { }
  };
  
  iterator begin() {
    return iterator();
  }

  const_iterator begin() const {
    return const_iterator();
  }
};

// This one compiles ok, using std::vector
class TestClassVector
{
public:
  void test() {
    vector<int>::const_iterator I=myc.begin();
  }

private:
  vector<int> myc;
};

// this one fails to compile. Why?
class TestClassMyContainer
{
public:
  void test(){
    MyContainer<int>::const_iterator I=myc.begin();
  }

private:
  MyContainer<int> myc;
};


int main(int argc, char ** argv)
{
  return 0;
}

gccは私に言います:

test2.C:メンバー関数内'void TestClassMyContainer :: test()':

test2.C:51:エラー:「MyContainer::iterator」から非スカラー型「MyContainer::const_iterator」への変換が要求されました

コンパイラーが、STLベクトルクラスではなく、自分のクラスのイテレーターをconst_iteratorに変換する場所と理由がわかりません。私は何が間違っているのですか?

4

3 に答える 3

10

begin()デフォルトでコンパイラを呼び出すと、non-constへの呼び出しが作成されますbegin()。はconstではないため、non-constではなくmycconstを使用することを意味していることを知る方法はありません。begin()begin()

iteratorSTLイテレータには、をサイレントに変換できるキャスト演算子が含まれていますconst_iterator。これを機能させたい場合は、次のように追加する必要があります。

class iterator
{
public:
    typedef iterator self_type;
    inline iterator() { }

    operator const_iterator() { return const_iterator(); }
};

またはそのようなものconst_iteratorから構築することを許可しますiterator

class const_iterator
{
public:
    typedef const_iterator self_type;

    const_iterator(iterator& ) {}
    inline const_iterator() { }
};
于 2010-05-16T15:57:03.987 に答える
3

コンテナではiterator、タイプはに変換可能である必要がありますconst_iterator。これは完全に理にかなっているため、非可変(const)イテレーターを使用して可変コンテナーを反復処理する場合に必要です。あなたの場合mycは可変(非定数)ですが、その上に定数イテレータを作成します。

于 2010-05-16T15:54:04.603 に答える
3

Boost.Iteratorsライブラリ、特にiterator_facadeiterator_adaptorセクションを確認する必要があります。それらには、「ゼロから」イテレータのビルドアップが含まれています。

const修飾自体を除けば、ほとんどの場合、constバージョンとnon-constバージョンのコードはほぼ同じであるため、あまり重複せずにイテレーターを作成する方法を示します。テンプレートを使用すると、一度作成してから2つの異なるタイプを宣言することができ、それがライブラリのドキュメントに示されています。

于 2010-05-17T06:29:52.210 に答える