Есть ли пример итератора, который не использовал бы ptrdiff_t в качестве его diff_type? - PullRequest
0 голосов
/ 17 сентября 2018

Я вижу, что iterator_traits всегда определяет difference_type: https://en.cppreference.com/w/cpp/iterator/iterator_traits#Member_types

Мне просто интересно, почему бы не быть ptrdiff_t для каждого типа?Есть ли пример итератора, который не использует ptrdiff_t?И если нет, то почему difference_type не исключено из iterator_traits и ptrdiff_t не используется везде?

Ответы [ 3 ]

0 голосов
/ 17 сентября 2018

Я написал тип веревки, который может работать с резервным хранилищем больше, чем потенциальная память (то есть он может работать с 64-битными последовательностями даже в 32-битном коде). И поэтому мне пришлось использовать 64-битные типы размеров и различий независимо от того, компилируется ли он в 32- или 64-битном режиме.

0 голосов
/ 17 сентября 2018

Теоретически, любой итератор, разница которого не может быть представлена ​​в std::ptrdiff_t.Рассмотрим, например, следующий игрушечный итератор, который, учитывая направление, перемещается по двумерной матрице:

template<typename T>
struct vec2d {T x; T y;};

template<typename T, typename C>
class cartesian_iterator {
public:
    using value_type = T;
    // because the difference between 2d vectors is an actual 2d vector,
    // we can't use std::ptrdiff_t
    using difference_type = vec2d<int>;

    cartesian_iterator(C* container, vec2d<size_t> position, difference_type increment = difference_type{1,1})
        :    container{container}, position{position}, increment{increment}
    {}

    cartesian_iterator& operator++() {position.x += increment.x; position.y += increment.y; return *this;}
    bool operator==(const cartesian_iterator& rhs) {return position.x == rhs.position.x && position.y == rhs.position.y;}
    bool operator!=(const cartesian_iterator& rhs) {return position.x != rhs.position.x || position.y != rhs.position.y;}
    T& operator*() {
        return (*container)[position.x][position.y];
    }

    // difference could be implemented like this
    difference_type operator-(const cartesian_iterator& rhs) {
        return {
            static_cast<int>(position.x) - static_cast<int>(rhs.position.x),
            static_cast<int>(position.y) - static_cast<int>(rhs.position.y),
        };
    }
private:
    C* container;
    vec2d<size_t> position;
    difference_type increment{1,1};
};

использование:

// outputs 159
int main() {
    using std::array;
    array<array<int, 3>, 3> a {
        1,2,3,
        4,5,6,
        7,8,9
    };
    cartesian_iterator<int, array<array<int, 3>, 3>> it{&a, {0, 0}};
    while (it != decltype(it){&a, {3,3}}) {
        std::cout << *it;
        ++it;
    }
}
0 голосов
/ 17 сентября 2018

Базовый итератор вывода, для которого std::ostream_iterator является одним из примеров, может вообще не нуждаться в типе разницы.

Поскольку это итератор типа «забей и забудь», обычно не имеет особого смысла получать разницу между двумя такими итераторами. Простой акт написания одной копии может сделать недействительными все остальные копии. Таким образом, ему не нужно будет определять тип разницы, и его не следует заставлять делать это искусственно (или навязывать ему тип).

...