COIN-OR::LEMON - Graph Library

Ticket #466: 466.diff

File 466.diff, 16.2 KB (added by Andras Kucsma, 5 years ago)

Implementation of safe_vector

  • new file lemon/safe_vector.h

    diff -r 5de6a70446f6 lemon/safe_vector.h
    - +  
     1#ifndef LEMON_SAFE_VECTOR_H
     2#define LEMON_SAFE_VECTOR_H
     3
     4#include <vector>
     5#include <cassert>
     6#include <iterator>
     7
     8#include <lemon/bits/enable_if.h>
     9
     10namespace lemon {
     11
     12template<class T, class Alloc>
     13class SafeVector;
     14
     15template<class V>
     16class SafeVectorIterator {
     17public:
     18    typedef V vector_type;
     19    typedef typename vector_type::iterator iterator_type;
     20    typedef typename vector_type::size_type size_type;
     21    typedef typename std::iterator_traits<iterator_type>::difference_type difference_type;
     22    typedef typename std::iterator_traits<iterator_type>::value_type value_type;
     23    typedef typename std::iterator_traits<iterator_type>::pointer pointer;
     24    typedef typename std::iterator_traits<iterator_type>::reference reference;
     25
     26    SafeVectorIterator() : vector_ptr(), index() {}
     27
     28    SafeVectorIterator(vector_type *vector_ptr, size_type index) :
     29        vector_ptr(vector_ptr), index(index) {}
     30
     31    reference operator*() { return (*vector_ptr)[index]; }
     32    const reference operator*() const { return (*vector_ptr)[index]; }
     33
     34    pointer operator->() { return &(*vector_ptr)[index]; }
     35    const pointer operator->() const { return &(*vector_ptr)[index]; }
     36
     37    SafeVectorIterator& operator++() { ++index; return *this; }
     38    SafeVectorIterator operator++(int) { return SafeVectorIterator(vector_ptr, index++); }
     39
     40    SafeVectorIterator& operator--() { --index; return *this; }
     41    SafeVectorIterator operator--(int) { return SafeVectorIterator(vector_ptr, index--); }
     42
     43    template<class Integer>
     44    SafeVectorIterator& operator+=(Integer rhs) {
     45        index += rhs;
     46        return *this;
     47    }
     48
     49    template<class Integer>
     50    SafeVectorIterator& operator-=(Integer rhs) {
     51        index -= rhs;
     52        return *this;
     53    }
     54
     55    const vector_type *get_vector_ptr() const { return vector_ptr; }
     56
     57    size_type get_index() const { return index; }
     58
     59    typename vector_type::value_type foo() { return typename V::value_type(); }
     60
     61private:
     62    vector_type *vector_ptr;
     63    size_type index;
     64};
     65
     66template <class V>
     67bool operator==(const SafeVectorIterator<V>& lhs, const SafeVectorIterator<V>& rhs) {
     68    assert(lhs.get_vector_ptr() && lhs.get_vector_ptr() == rhs.get_vector_ptr());
     69    return lhs.get_index() == rhs.get_index();
     70}
     71
     72template <class V>
     73bool operator!=(const SafeVectorIterator<V>& lhs, const SafeVectorIterator<V>& rhs) {
     74    assert(lhs.get_vector_ptr() && lhs.get_vector_ptr() == rhs.get_vector_ptr());
     75    return lhs.get_index() != rhs.get_index();
     76}
     77
     78template <class V>
     79bool operator<(const SafeVectorIterator<V>& lhs, const SafeVectorIterator<V>& rhs) {
     80    assert(lhs.get_vector_ptr() && lhs.get_vector_ptr() == rhs.get_vector_ptr());
     81    return lhs.get_index() < rhs.get_index();
     82}
     83
     84template <class V>
     85bool operator<=(const SafeVectorIterator<V>& lhs, const SafeVectorIterator<V>& rhs) {
     86    assert(lhs.get_vector_ptr() && lhs.get_vector_ptr() == rhs.get_vector_ptr());
     87    return lhs.get_index() <= rhs.get_index();
     88}
     89
     90template <class V>
     91bool operator>(const SafeVectorIterator<V>& lhs, const SafeVectorIterator<V>& rhs) {
     92    assert(lhs.get_vector_ptr() && lhs.get_vector_ptr() == rhs.get_vector_ptr());
     93    return lhs.get_index() > rhs.get_index();
     94}
     95
     96template <class V>
     97bool operator>=(const SafeVectorIterator<V>& lhs, const SafeVectorIterator<V>& rhs) {
     98    assert(lhs.get_vector_ptr() && lhs.get_vector_ptr() == rhs.get_vector_ptr());
     99    return lhs.get_index() >= rhs.get_index();
     100}
     101
     102template <class V, class Integer>
     103SafeVectorIterator<V> operator+(const SafeVectorIterator<V>& lhs, Integer rhs) {
     104    return SafeVectorIterator<V>(lhs.get_vector_ptr(), lhs.get_index() + rhs);
     105}
     106
     107template <class V, class Integer>
     108SafeVectorIterator<V> operator+(Integer lhs, const SafeVectorIterator<V>& rhs) {
     109    return SafeVectorIterator<V>(rhs.get_vector_ptr(), lhs + rhs.get_index());
     110}
     111
     112template <class V, class Integer>
     113SafeVectorIterator<V> operator-(const SafeVectorIterator<V>& lhs, Integer rhs) {
     114    return SafeVectorIterator<V>(lhs.get_vector_ptr(), lhs.get_index() - rhs);
     115}
     116
     117template <class V, class Integer>
     118SafeVectorIterator<V> operator-(Integer lhs, const SafeVectorIterator<V>& rhs) {
     119    return SafeVectorIterator<V>(rhs.get_vector_ptr(), lhs - rhs.get_index());
     120}
     121
     122template <class V>
     123typename SafeVectorIterator<V>::difference_type operator-(
     124        const SafeVectorIterator<V>& lhs,
     125        const SafeVectorIterator<V>& rhs)
     126{
     127    assert(lhs.get_vector_ptr() && lhs.get_vector_ptr() == rhs.get_vector_ptr());
     128    return SafeVectorIterator<V>(lhs.get_vector_ptr(), lhs.get_index() - rhs.get_index());
     129}
     130
     131#define LEMON_DEFINE_BINARY_OPERATOR(op) \
     132    IndexType& operator op ## =(const IndexType& rhs) { \
     133        assert(vector_ptr && vector_ptr == rhs.vector_ptr); \
     134        index op ## = rhs.index; \
     135        return *this; \
     136    } \
     137    IndexType& operator op ## =(size_type rhs) { \
     138        assert(vector_ptr); \
     139        index op ## = rhs; \
     140        return *this; \
     141    } \
     142    IndexType operator op(const IndexType& rhs) { \
     143        assert(vector_ptr && vector_ptr == rhs.vector_ptr); \
     144        IndexType nrv(*this); \
     145        nrv op ## = rhs; \
     146        return nrv; \
     147    } \
     148    IndexType operator op(size_type rhs) { \
     149        IndexType nrv(*this); \
     150        nrv op ## = rhs; \
     151        return nrv; \
     152    }
     153
     154#define LEMON_DEFINE_COMP_OPERATOR(op) \
     155    template<class V> \
     156    bool operator op(const IndexType<V>& lhs, const IndexType<V>& rhs) { \
     157        assert(lhs.get_vector_ptr() && lhs.get_vector_ptr() == rhs.get_vector_ptr()); \
     158        return lhs.get_index() op rhs.get_index(); \
     159    } \
     160    template<class V> \
     161    bool operator op(typename IndexType<V>::size_type lhs, const IndexType<V>& rhs) { \
     162        assert(rhs.get_vector_ptr()); \
     163        return lhs op rhs.get_index(); \
     164    } \
     165    template<class V> \
     166    bool operator op(const IndexType<V>& lhs, typename IndexType<V>::size_type rhs) { \
     167        assert(lhs.get_vector_ptr()); \
     168        return lhs.get_index() op rhs; \
     169    }
     170
     171#define LEMON_DEFINE_INC_OPERATOR(op) \
     172    IndexType& operator op() { \
     173        assert(vector_ptr); \
     174        op index; \
     175        return *this; \
     176    } \
     177    IndexType operator op(int) { \
     178        assert(vector_ptr); \
     179        IndexType res(*this); \
     180        op *this; \
     181        return res; \
     182    }
     183
     184template<class V>
     185struct IndexType {
     186    typedef V vector_type;
     187    typedef typename V::size_type size_type;
     188
     189    IndexType() : index(), vector_ptr() {}
     190    IndexType(const vector_type *vector_ptr, size_type index) : vector_ptr(vector_ptr), index(index) {}
     191
     192    size_type get_index() const { return index; }
     193    const vector_type *get_vector_ptr() const { return vector_ptr; }
     194
     195    operator size_type() const { return index; }
     196
     197    LEMON_DEFINE_BINARY_OPERATOR(+);
     198    LEMON_DEFINE_BINARY_OPERATOR(-);
     199    LEMON_DEFINE_BINARY_OPERATOR(*);
     200    LEMON_DEFINE_BINARY_OPERATOR(/);
     201    LEMON_DEFINE_BINARY_OPERATOR(%);
     202    LEMON_DEFINE_BINARY_OPERATOR(|);
     203    LEMON_DEFINE_BINARY_OPERATOR(&);
     204    LEMON_DEFINE_BINARY_OPERATOR(^);
     205
     206    LEMON_DEFINE_INC_OPERATOR(++);
     207    LEMON_DEFINE_INC_OPERATOR(--);
     208
     209private:
     210    const vector_type *vector_ptr;
     211    size_type index;
     212};
     213
     214LEMON_DEFINE_COMP_OPERATOR(==);
     215LEMON_DEFINE_COMP_OPERATOR(!=);
     216LEMON_DEFINE_COMP_OPERATOR(<);
     217LEMON_DEFINE_COMP_OPERATOR(>);
     218LEMON_DEFINE_COMP_OPERATOR(<=);
     219LEMON_DEFINE_COMP_OPERATOR(>=);
     220
     221#undef LEMON_DEFINE_INC_OPERATOR
     222#undef LEMON_DEFINE_BINARY_OPERATOR
     223#undef LEMON_DEFINE_COMP_OPERATOR
     224
     225template<class T, class Alloc = std::allocator<T> >
     226class SafeVector {
     227public:
     228    typedef std::vector<T, Alloc> vector_type;
     229    typedef typename vector_type::value_type value_type;
     230    typedef typename vector_type::allocator_type allocator_type;
     231    typedef typename vector_type::reference reference;
     232    typedef typename vector_type::const_reference const_reference;
     233    typedef typename vector_type::pointer pointer;
     234    typedef typename vector_type::const_pointer const_pointer;
     235    typedef typename vector_type::iterator iterator;
     236    typedef typename vector_type::const_iterator const_iterator;
     237    typedef typename vector_type::reverse_iterator reverse_iterator;
     238    typedef typename vector_type::const_reverse_iterator const_reverse_iterator;
     239
     240    //TODO possible improvement: permanent_const_iterator, permanent_reverse_iterator, etc
     241    typedef SafeVectorIterator<vector_type> permanent_iterator;
     242
     243    typedef typename vector_type::difference_type difference_type;
     244    typedef typename vector_type::size_type size_type;
     245
     246#ifdef NDEBUG
     247    typedef size_type index_type;
     248#else
     249    typedef IndexType<vector_type> index_type;
     250#endif
     251
     252    explicit SafeVector(const allocator_type& alloc = allocator_type()) :
     253        vector(alloc) {}
     254
     255    explicit SafeVector(size_type n, const value_type& val = value_type(),
     256            const allocator_type& alloc = allocator_type()) :
     257        vector(n, val, alloc) {}
     258
     259    template <class InputIterator>
     260    SafeVector(InputIterator first, InputIterator last,
     261            const allocator_type& alloc = allocator_type()) :
     262        vector(first, last, alloc) {}
     263
     264    SafeVector(const vector_type& other) : vector(other) {}
     265    SafeVector(const SafeVector& other) : vector(other.vector) {}
     266
     267    SafeVector& operator=(const vector_type& other) {
     268        vector = other;
     269        return *this;
     270    }
     271
     272    SafeVector& operator=(const SafeVector& other) {
     273        vector = other.vector;
     274        return *this;
     275    }
     276
     277    index_type get_index(size_type index) {
     278#ifdef NDEBUG
     279        return index;
     280#else
     281        return index_type(&vector, index);
     282#endif
     283    }
     284
     285    iterator begin() { return vector.begin(); }
     286    const_iterator begin() const { return vector.begin(); }
     287
     288    iterator end() { return vector.end(); }
     289    const_iterator end() const { return vector.end(); }
     290
     291    reverse_iterator rbegin() { return vector.rbegin(); }
     292    const_reverse_iterator rbegin() const { return vector.rbegin(); }
     293
     294    reverse_iterator rend() { return vector.rend(); }
     295    const_reverse_iterator rend() const { return vector.rend(); }
     296
     297    permanent_iterator pbegin() { return permanent_iterator(&vector, 0); }
     298    permanent_iterator pbegin() const { return permanent_iterator(vector, 0); }
     299
     300    permanent_iterator pend() { return permanent_iterator(&vector, size()); }
     301    permanent_iterator pend() const { return permanent_iterator(&vector, size()); }
     302
     303    size_type size() const { return vector.size(); }
     304    size_type max_size() const { return vector.max_size(); }
     305
     306    void resize(size_type n, value_type val = value_type()) {
     307        vector.resize(n, val);
     308    }
     309
     310    size_type capacity() const { return vector.capacity(); }
     311
     312    bool empty() const { return vector.empty(); }
     313
     314    void reserve(size_type n) { return vector.reserve(n); }
     315
     316    reference operator[](size_type n) { return vector[n]; }
     317    const_reference operator[](size_type n) const { return vector[n]; }
     318#ifndef NDEBUG
     319    reference operator[](index_type n) {
     320       assert(n.get_vector_ptr() == &vector);
     321       assert(n.get_index() < size());
     322       return vector[n.get_index()];
     323    }
     324    const_reference operator[](index_type n) const {
     325       assert(n.get_vector_ptr() == &vector);
     326       assert(n.get_index() < size());
     327       return vector[n.get_index()];
     328    }
     329#endif
     330
     331    reference at(size_type n) { return vector.at(n); }
     332    const_reference at(size_type n) const { return vector.at(n); }
     333#ifndef NDEBUG
     334    reference at(index_type n) {
     335       assert(n.get_vector_ptr() == &vector);
     336       return vector.at(n.get_index());
     337    }
     338    const_reference at(index_type n) const {
     339       assert(n.get_vector_ptr() == &vector);
     340       return vector.at(n.get_index());
     341    }
     342#endif
     343
     344    reference front() { return vector.front(); }
     345    const_reference front() const { return vector.front(); }
     346
     347    reference back() { return vector.back(); }
     348    const_reference back() const { return vector.back(); }
     349
     350    template <class InputIterator>
     351    void assign(InputIterator first, InputIterator last) {
     352        vector.assign(first, last);
     353    }
     354
     355    void assign(size_type n, const value_type& val) {
     356        vector.assign(n, val);
     357    }
     358
     359    void push_back(const value_type& val) { vector.push_back(val); }
     360
     361    void pop_back() { vector.pop_back(); }
     362
     363    iterator insert(iterator position, const value_type& val) {
     364        return vector.insert(position, val);
     365    }
     366
     367    void insert(iterator position, size_type n, const value_type& val) {
     368        return vector.insert(position, n, val);
     369    }
     370
     371    template <class InputIterator>
     372    void insert(iterator position, InputIterator first, InputIterator last) {
     373        vector.insert(position, first, last);
     374    }
     375
     376    iterator erase(iterator position) { return vector.erase(position); }
     377
     378    iterator erase(iterator first, iterator last) {
     379        return vector.erase(first, last);
     380    }
     381
     382    void swap(SafeVector& other) {
     383        vector.swap(other.vector);
     384    }
     385
     386    void clear() { vector.clear(); }
     387
     388    allocator_type get_allocator() const { return vector.get_allocator(); }
     389
     390    vector_type& get_vector() { return vector; }
     391    const vector_type& get_vector() const { return vector; }
     392
     393private:
     394    vector_type vector;
     395};
     396
     397template <class T, class Alloc>
     398bool operator==(const SafeVector<T, Alloc>& lhs, const SafeVector<T, Alloc>& rhs) {
     399    return lhs.get_vector() == rhs.get_vector();
     400}
     401
     402template <class T, class Alloc>
     403bool operator!=(const SafeVector<T, Alloc>& lhs, const SafeVector<T, Alloc>& rhs) {
     404    return lhs.get_vector() != rhs.get_vector();
     405}
     406
     407template <class T, class Alloc>
     408bool operator<(const SafeVector<T, Alloc>& lhs, const SafeVector<T, Alloc>& rhs) {
     409    return lhs.get_vector() < rhs.get_vector();
     410}
     411
     412template <class T, class Alloc>
     413bool operator<=(const SafeVector<T, Alloc>& lhs, const SafeVector<T, Alloc>& rhs) {
     414    return lhs.get_vector() <= rhs.get_vector();
     415}
     416
     417template <class T, class Alloc>
     418bool operator>(const SafeVector<T, Alloc>& lhs, const SafeVector<T, Alloc>& rhs) {
     419    return lhs.get_vector() > rhs.get_vector();
     420}
     421
     422template <class T, class Alloc>
     423bool operator>=(const SafeVector<T, Alloc>& lhs, const SafeVector<T, Alloc>& rhs) {
     424    return lhs.get_vector() >= rhs.get_vector();
     425}
     426
     427
     428}
     429
     430#endif
  • test/CMakeLists.txt

    diff -r 5de6a70446f6 test/CMakeLists.txt
    a b  
    4646  min_cost_flow_test
    4747  min_mean_cycle_test
    4848  nagamochi_ibaraki_test
     49  safe_vector_test
    4950  path_test
    5051  planarity_test
    5152  radix_sort_test
  • new file test/safe_vector_test.cc

    diff -r 5de6a70446f6 test/safe_vector_test.cc
    - +  
     1
     2#ifdef NDEBUG
     3#undef NDEBUG
     4#endif
     5
     6#include <lemon/safe_vector.h>
     7#include "test_tools.h"
     8
     9using namespace lemon;
     10
     11int main() {
     12
     13    {
     14        SafeVector<int> v;
     15        for (int i = 0; i < 10; ++i) {
     16            v.push_back(i);
     17        }
     18
     19        int i = 0;
     20        for (SafeVector<int>::permanent_iterator it = v.pbegin(); it != v.pend(); ++it) {
     21            check(*it == i++, "Content check failed");
     22        }
     23    }
     24    {
     25        SafeVector<std::string> v;
     26        for (unsigned i = 0; i < 10; ++i) {
     27            v.push_back(std::string(i, '*'));
     28        }
     29
     30        unsigned i = 0;
     31        for (SafeVector<std::string>::permanent_iterator it = v.pbegin(); it < v.pend(); it += 1) {
     32            check(it->size() == i++, "Content check failed");
     33        }
     34    }
     35    {
     36        SafeVector<int> v;
     37        for (int i = 0; i < 10; ++i) {
     38            v.push_back(i);
     39        }
     40
     41        for (SafeVector<int>::index_type i = v.get_index(0); i < v.size(); ++i) {
     42            check(static_cast<SafeVector<int>::size_type>(v[i]) == i, "Content check failed");
     43        }
     44    }
     45    {
     46        SafeVector<int> v;
     47        for (int i = 0; i < 10; ++i) {
     48            v.push_back(i);
     49        }
     50
     51        for (SafeVector<int>::index_type i = v.get_index(0); i != v.size(); i += 1) {
     52            check(static_cast<SafeVector<int>::size_type>(v.at(i)) == i, "Content check failed");
     53        }
     54    }
     55}