Question

I currently have the following function to read an array or a vector of raw data (_readStream is a 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 question : does this function seem ok for you ?

As we read directly a block of memory, it will only work if the memory block from first to last is contiguous in memory. How to check that ?

Was it helpful?

Solution

Leaving aside your sample function, you can never be completely sure that iterators will form a contiguous memory without checking the address of every element between the two.

A reasonable sanity test, though, would be to just check if the memory area between the two is the same as the count between the two:

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

OTHER TIPS

n4183 is a paper that goes over the idea of adding a contiguous iterator trait. It is currently under consideration for C++1z (hopefully C++17).

Under it, you can do std::is_contiguous_iterator<It>::value and get if It is a contiguous iterator or not. (This will require support from the designer of the iterator).

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

This is useless because std::iterator_traits has a primary template with an unconditonally defined member type iterator_category. It is tacitly assumed that the template parameter is an iterator and that it's a precondition violation if it isn't -- as such you won't get SFINAE but a hard error if the above is attempted with an invalid instantiation.

As we read directly a block of memory, it will only work if the memory block from first to last is contiguous in memory. How to check that ?

I don't know what exact requirements you would put on a 'contiguous in memory' concept. Have you however considered the following?

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

with the precondition that [ first, last ) be a valid pointer-as-iterator range into an array.

If you want to put further requirements on T (e.g. trivial copyability since you make use of read) you can express/document those, too.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top