简体   繁体   中英

checked_array_iterator<T> in C++11

C++11 provides std::array<T> to wrap C arrays, but only where you know the array size at compile time. What is the best way of handling arrays whose size is only known at runtime?

Background

I'm porting some code from MSVC to GCC. MSVC provides the stdext::checked_array_iterator<T> template to provide some protection for lines of code such as this:

std::copy(v.begin(), v.end(), stdext::checked_array_iterator<int*>(arr, numVals));

So far I can think of two options: abandoning the safety check or writing my own implementation. On that note, I'd be grateful for any constructive comments on this implementation:

namespace stdext {
    template<typename T>
    struct checked_array_iterator
    {
    private:
        T _val;
        size_t _len;
    public:
        typedef typename std::remove_pointer<T>::type value_type;
        checked_array_iterator(T val, size_t len) : _val(val), _len(len) {}
        checked_array_iterator<T> operator++(int)
        {
            if(_len == 0)
                throw std::range_error("Array iterator overrun");
            checked_array_iterator<T> retval = *this;
            _val++;
            _len--;
            return retval;
        }
        checked_array_iterator<T> & operator++()
        {
            if(_len == 0)
                throw std::range_error("Array iterator overrun");
            _val++;
            _len--;
            return *this;
        }
        value_type & operator*()
        {
            return *_val;
        }
        bool operator==(checked_array_iterator<T>& other) { return other._val == _val; }
        bool operator!=(checked_array_iterator<T>& other) { return !(other == *this); }
        T operator->() { return _val; }
    };
}
namespace std
{
    template <typename T>
    struct iterator_traits<stdext::checked_array_iterator<T>>
    {
        typedef std::ptrdiff_t difference_type;
        typedef typename std::remove_pointer<T>::type value_type;
        typedef T pointer;
        typedef value_type& reference;
        typedef std::input_iterator_tag iterator_category;
    };
}

Would this be so bad?

if (v.size() > numVals)
  throw std::runtime_error("oops");
std::copy(v.begin(), v.end(), arr);

It's more efficient too, because it checks just once that the size is OK, rather than once per element.

In some cases, you could use Eigen Map (or write a similar implementation). It is essentially a vector which does not manage its own storage but gets pointer and size in its constructor. In that regard, it is quite similar to the level of safety provided by stdext::checked_array_iterator<T> . On the other hand, it is not meant to be an iterator, it is meant to be a matrix (or vector as a special case) class. Ane Eigen is both free and multi-platform.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM