有没有将ptrdiff_t用作difference_type的迭代器的示例?

时间:2018-09-17 15:55:09

标签: c++ iterator distance difference iterator-traits

我看到iterator_traits总是定义一个difference_typehttps://en.cppreference.com/w/cpp/iterator/iterator_traits#Member_types

我只是想知道为什么不是每种类型都是ptrdiff_t吗?是否有一个不使用ptrdiff_t的迭代器的示例?如果不是,为什么不从各处使用的difference_typeiterator_traits中删除ptrdiff_t

3 个答案:

答案 0 :(得分:8)

我写了一个绳索类型,它可以处理比潜在内存更大的后备存储(也就是说,即使使用32位代码,它也可以处理64位序列)。因此,无论是32位还是64位模式,我都必须使用64位大小和差异类型。

答案 1 :(得分:5)

std::ostream_iterator为例的基本输出迭代器可能根本不需要差异类型。

由于它本来是一种“抛弃式”迭代器,所以在两个此类迭代器之间取得区别通常没有多大意义。仅写一份副本的行为可能会使所有其他副本无效。因此,它不需要定义差异类型,也不必强行人工定义(或强加类型)。

答案 2 :(得分:1)

从理论上讲,任何差异不能在std::ptrdiff_t中表示的迭代器。例如,考虑以下玩具迭代器,该玩具迭代器在给定方向的情况下可以导航2d矩阵:

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