2016-09-29 8 views
0

以前はイテレータで作業したことがありません。私が書いたカスタムコンテナクラスのカスタムイテレータを設計するのに問題があります。C++ Iterators戻り値の型

背景:

class RandomArray 
{ 
friend ostream& operator<<(ostream&, const RandomArray&); 

public: 
    class iterator 
    { 
    public: 
     typedef iterator self_type; 
     typedef int* pointer; 
     typedef int& reference; 
     self_type operator++() { self_type i = *this; ptr++; return i;} 
     reference operator*() {return *ptr;} 
     bool operator!=(const self_type& rhs) {return ptr != rhs.ptr;} 
    private: 
     pointer ptr; 
    }; 

    class const_iterator 
    { 
    public: 
     typedef const_iterator self_type; 
     typedef int* pointer; 
     typedef int& reference; 
     self_type operator++() { self_type i = *this; ptr++; return i;} 
     const reference operator*() { return *ptr; } 
     bool operator!=(const self_type& rhs) {return ptr != rhs.ptr;} 
    private: 
     pointer ptr; 
    }; 

    RandomArray(); 

    RandomArray(size_t); 

    size_t size() const; 

    int* begin(); 
    iterator begin(); 

    const int* begin() const; 
    const iterator begin() const; 

    int* end(); 
    iterator end(); 

    const int* end() const; 
    const iterator end() const; 
private: 
    size_t capacity; 
    int* data; 
}; 

私は「エラー:

TEST(RandomArray, End) { 
    RandomArray r(17); 
    int *b = r.begin(); 
    int *e = r.end(); 
    EXPECT_EQ(b + 17, e); 
} 

TEST(RandomArray, IteratorTypedef) { 
    RandomArray r(7); 
    for (RandomArray::iterator it = r.begin(); it != r.end(); ++it) { 
     *it = 89; 
     EXPECT_EQ(89, *it); 
    } 
} 

はここに私のヘッダファイルとイテレータのコードです:これらは私が持っている2つのテストケースをされている、GoogleがAPIをテスト使用最初と最後になるのは次のようなものです:Error: Cannot overload functions distinguished by return type alone.

同じ関数名と同じパラメータを異なる戻り値の型で使用することはできませんこれを行うより良い方法があるのだろうか?イテレーターを正しく作っていますか?テンプレートはこれを解決するのに役立つでしょうか? int*iteratorの両方を返すには、begin()end()が必要です。両方のテストケースを渡すことができます。これを達成するより良い方法はありますか?

+1

は、ポインタリターンを取り除くだけイテレータを返しなさい!

は、コードを更新しましたか – NathanOliver

+0

テストケースを修正してください。彼らが求めているものは不可能です。 – ubik

答えて

2

私はそう、私は両方のテストケースを渡すことができint*iteratorの両方を返すためにbegin()end()を必要としています。

いいえ、ありません。ポインターが期待されるテストケースが間違っています。コンテナはイテレータを戻します。あなたの場合、イテレータはとなります。ポインタですが、それは実装の詳細です。

iterator begin(); 
const_iterator begin() const; // NB: const_iterator, not const iterator 

をそしてRandomArray::iteratorの代わりint*を期待するあなたのユニットテストを修正する:あなたは間違いなくちょうど欲しいです。あるいは、さらに良いものは、autoです。


注:operator++()は、接頭辞の増分ではなく、後続の増分を行います。また、const referenceが間違ったタイプであり、それはint& constであり、参照は本質的にconstです。 referenceのtypedefをint const&に変更したいとします。

0

あなたはint *b = r.begin();でテストケースを変更できない場合(これは新しいクラスである場合も、なぜいけないのでしょうか?)、あなたはあなたのイテレータ型ポインタ型で作る、またはに変換するいずれかの必要がありますポインタ型

最初のケースでは、iteratorクラスを取り除き、using iterator = int*;using const_iterator = int const*;と書きます。

2番目のケースでは、変換関数operator pointer() const { return ptr; }を追加します。

次のケースでは、変換関数を将来廃止することができます。しかし、iterator型を使用するようにテストケースを修正する方が良いでしょう。

0

私が間違っていたことを理解しました。私がしなければならなかったのは、typedefイテレータをint *として宣言することだけでした。関数本体に、私はこれにそれを変更し、その後

class MyClass 
{ 
public: 
    int* begin(); 

    const int* begin() const; 

    int* end(); 

    const int* end() const; 

    //HERE 
    typedef int* iterator; 
    typedef const int* const_iterator; 
private: 
    size_t capacity; 
    int* data; 
}; 

int* MyClass::begin() 
{ 
    return iterator(&data[0]); 
} 

const int* MyClass::begin() const 
{ 
    return const_iterator(&data[0]); 
} 

int* MyClass::end() 
{ 
    return iterator(&data[capacity]); 
} 

const int* MyClass::end() const 
{ 
    return const_iterator(&data[capacity]); 
} 
+0

'iterator(&data [0])'は 'iterator(data)'と 'data'と同じことです。すべての余分なものの必要はありません。 – Barry