2016-09-29 2 views
0

Я никогда раньше не работал с итераторами, и у меня возникли проблемы с созданием пользовательского итератора для пользовательского класса контейнеров, который я написал.C++ Iterators return type

фона: Использование Google Тесты API, эти два случая испытаний, которые у меня есть:

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); 
    } 
} 

Вот мой файл заголовка и код для итераторов:

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; 
}; 

Ошибка I» m Начало и конец: Error: Cannot overload functions distinguished by return type alone.

Я знаю, что вам не разрешено иметь одно и то же имя функции и одинаковые параметры с разными типами возврата, поэтому я интересно, есть ли лучший способ сделать это? Я правильно делаю итератор? Помог ли шаблон исправить это? Мне нужны begin() и end(), чтобы вернуть как int*, так и iterator, поэтому я могу сдать оба тестовых примера. Есть ли лучший способ сделать это?

+1

Избавиться от возвращения указателя и возвращать только итераторы? – NathanOliver

+0

И исправьте тестовые чехлы, то, что они просят, невозможно. – ubik

ответ

2

мне нужно begin() и end() вернуться одновременно int* и iterator, так что я могу передать оба случая теста.

Нет, вы этого не сделаете. Тестовый пример, ожидающий указателя, неверен. Контейнеры возвращают вам итераторы. В вашем случае ваш итератор может быть указателем, но это деталь реализации. Вы, безусловно, просто хочу:

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

А затем исправить модульное тестирование ожидать RandomArray::iterator вместо int*. Или, еще лучше, auto.


Примечания: Ваш operator++() делает постфиксное приращение вместо приращения префикса. Также const reference - неправильный тип, который woudl будет int& const, а ссылки по существу const. Вы хотите изменить свой typedef для reference себе int const&.

0

Если вы не можете изменить тестовый случай с int *b = r.begin(); (хотя, если это новый класс, то почему бы и нет?), То вам нужно либо сделать свой итератор типа быть тип указателя, или быть конвертируемые в тип указателя.

В первом случае избавиться от классов iterator и написать using iterator = int*;using const_iterator = int const*;.

Во втором случае добавьте функции преобразования operator pointer() const { return ptr; }.

Второй случай лучше, так как это позволяет в будущем отказаться от функции преобразования. Однако было бы еще лучше исправить тестовый пример, чтобы использовать тип итератора.

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])' это то же самое, что итератор (данные) 'это то же самое, что и' data'. Нет необходимости в дополнительных материалах. – Barry