Как проверить, образуют ли итераторы непрерывную зону памяти?

В настоящее время у меня есть следующая функция для чтения массива или вектора необработанных данных (_readStream это std::ifstream):

template<typename IteratorType>
inline bool MyClass::readRawData(
const IteratorType& first,
const IteratorType& last,
typename std::iterator_traits<IteratorType>::iterator_category* = nullptr
)
{
_readStream.read(reinterpret_cast<char*>(&*first), (last-first)*sizeof(*first));
return _readStream.good();
}

Первый вопрос: эта функция вам подходит?

Поскольку мы читаем непосредственно блок памяти, он будет работать, только если блок памяти из first в last смежна в памяти. Как это проверить?

5

Решение

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

Тем не менее, разумным тестом будет просто проверить, совпадает ли область памяти между ними с количеством между ними:

assert(&*last - &*first == last - first &&
"Iterators must represent a contiguous memory region");
4

Другие решения

n4183 это статья, в которой рассматривается идея добавления смежной черты итератора. В настоящее время рассматривается C ++ 1z (возможно, C ++ 17).

Под ним можно сделать std::is_contiguous_iterator<It>::value и получить, если It является смежным итератором или нет. (Это потребует поддержки от дизайнера итератора).

3

typename std::iterator_traits<IteratorType>::iterator_category* = nullptr

Это бесполезно, потому что std::iterator_traits имеет основной шаблон с неопределенным типом элемента iterator_category, Предполагается, что параметр шаблона является итератором и является нарушением предусловия, если это не так — поэтому вы не получите SFINAE, но получите серьезную ошибку, если попытка выполнить вышеупомянутое произойдет с неверной реализацией.

Поскольку мы читаем непосредственно блок памяти, он будет работать только в том случае, если блок памяти от первого до последнего является непрерывным в памяти. Как это проверить?

Я не знаю, какие именно требования вы бы выдвинули к концепции «смежных в памяти». Однако учли ли вы следующее?

template<typename T>
bool readRawData(T* first, T* last);

с условием, что [ first, last ) быть допустимым диапазоном указатель как итератор в массив.

Если вы хотите поставить дополнительные требования T (например, тривиальное копирование, так как вы используете read) Вы можете выразить / документировать их тоже.

2
По вопросам рекламы [email protected]