2016-07-25 2 views
2

Моя цель - научиться писать пользовательский итератор с нуля. Я написал следующий итератор:Реализация пользовательского итератора для работы с std :: sort

#include <iterator> 

template<class D> 
class SpanIterator final : public std::iterator<std::random_access_iterator_tag, D> 
{ 
private: 
    D* _data; 

public: 
    explicit SpanIterator(D* data) : 
     _data{ data } 
    { 
    } 

    SpanIterator(const SpanIterator& itertator) = default; 

    SpanIterator& operator=(const SpanIterator& iterator) = default; 

    SpanIterator& operator=(D* data) 
    { 
     _data = data; 

     return *this; 
    } 

    operator bool() const 
    { 
     return _data != nullptr; 
    } 

    bool operator==(const SpanIterator& itertator) const 
    { 
     return _data == itertator._data; 
    } 

    bool operator!=(const SpanIterator& itertator) const 
    { 
     return _data != itertator._data; 
    } 

    SpanIterator& operator+=(const std::ptrdiff_t& movement) 
    { 
     _data += movement; 

     return *this; 
    } 

    SpanIterator& operator-=(const std::ptrdiff_t& movement) 
    { 
     _data -= movement; 

     return *this; 
    } 

    SpanIterator& operator++() 
    { 
     ++_data; 

     return *this; 
    } 

    SpanIterator& operator--() 
    { 
     --_data; 

     return *this; 
    } 

    SpanIterator operator++(int) 
    { 
     auto temp = *this; 

     ++_data; 

     return temp; 
    } 

    SpanIterator operator--(int) 
    { 
     auto temp = *this; 

     --_data; 

     return temp; 
    } 

    SpanIterator operator+(const std::ptrdiff_t& movement) 
    { 
     auto oldPtr = _data; 

     _data += movement; 

     auto temp = *this; 

     _data = oldPtr; 

     return temp; 
    } 

    SpanIterator operator-(const std::ptrdiff_t& movement) 
    { 
     auto oldPtr = _data; 

     _data -= movement; 

     auto temp = *this; 

     _data = oldPtr; 

     return temp; 
    } 

    D& operator*() 
    { 
     return *_data; 
    } 

    const D& operator*() const 
    { 
     return *_data; 
    } 

    D& operator->() 
    { 
     return _data; 
    } 
}; 

Что я тестирование, как так:

#include <iostream> 
#include <array> 

int main() 
{ 
    std::array<double, 3> values = { 1, 2, 1 }; 

    SpanIterator<double> begin{ values.data() }; 
    SpanIterator<double> end{ values.data() + values.size() }; 

    std::sort(begin, end); 

    return EXIT_SUCCESS; 
} 

Однако не может скомпилировать, что дает следующие ошибки:

  • Ошибка C2666 «SpanIterator: : оператор - ': 2 перегрузки
  • Ошибка C2780' void std :: _ Sort_unchecked1 (_RanIt, _RanIt, _Diff, _Pr &) ': ожидает 4 аргументов - 3 при условии

Если удалить SpanIterator operator-(const std::ptrdiff_t& movement) я получаю различные ошибки:

  • Пустота станд :: _ Guess_median_unchecked (_RanIt, _RanIt, _RanIt, _Pr &) ': не может вывести шаблон аргумент «_RanIt» из «» междунара
  • «_Guess_median_unchecked»: нет соответствия перегруженной функции не найдена
  • ошибки C2100 нелегального косвенность

ответ

4

Вы упускаете операторы для поддержки following operations (где a и b являются значение вашего итератора типа SpanIterator<...>):

  • b - a
  • a < b (и остальные сравнения, хотя большинство реализаций std::sort Дона» t использовать их).

Например, вы можете предоставить следующий оператор члена перегрузки:

std::ptrdiff_t operator-(SpanIterator const&) const; 
bool operator<(SpanIterator const&) const; 
// etc. 

(Обратите внимание, что перегружает, не являющиеся члены часто являются предпочтительными: Operator overloading)

Кроме того, ваш operator bool должен быть explicit чтобы избежать неоднозначных перегрузок для операций a + n, n + a и b - a (где n - значение вашего разностного типа, то есть std::ptrdiff_t).

+0

Добавление явного к 'operator bool' и добавление двух упомянутых вами операторов сделали трюк - спасибо вам :-) – keith

Смежные вопросы