я вижу это 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
используется везде?
Основной выходной итератор, с std::ostream_iterator
будучи одним из примеров, может вообще не нуждаться в типе различий.
Поскольку это итератор типа «запусти и забудь», обычно нет особого смысла получать разницу между двумя такими итераторами. Простой акт написания одной копии может сделать недействительными все остальные копии. Таким образом, ему не нужно определять тип различий, и его не следует заставлять делать это искусственно (или навязывать этот тип).
Я написал тип веревки, который может работать с резервным хранилищем больше, чем потенциальная память (то есть он может работать с 64-битными последовательностями даже в 32-битном коде). И поэтому мне пришлось использовать 64-битный размер и типы различий независимо от того, был ли он скомпилирован в 32- или 64-битном режиме.
Теоретически, любой итератор, чье различие не может быть представлено в 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;
}
}