diff -r 5de6a70446f6 lemon/safe_vector.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lemon/safe_vector.h	Tue Nov 25 14:52:27 2014 +0100
@@ -0,0 +1,430 @@
+#ifndef LEMON_SAFE_VECTOR_H
+#define LEMON_SAFE_VECTOR_H
+
+#include <vector>
+#include <cassert>
+#include <iterator>
+
+#include <lemon/bits/enable_if.h>
+
+namespace lemon {
+
+template<class T, class Alloc>
+class SafeVector;
+
+template<class V>
+class SafeVectorIterator {
+public:
+    typedef V vector_type;
+    typedef typename vector_type::iterator iterator_type;
+    typedef typename vector_type::size_type size_type;
+    typedef typename std::iterator_traits<iterator_type>::difference_type difference_type;
+    typedef typename std::iterator_traits<iterator_type>::value_type value_type;
+    typedef typename std::iterator_traits<iterator_type>::pointer pointer;
+    typedef typename std::iterator_traits<iterator_type>::reference reference;
+
+    SafeVectorIterator() : vector_ptr(), index() {}
+
+    SafeVectorIterator(vector_type *vector_ptr, size_type index) :
+        vector_ptr(vector_ptr), index(index) {}
+
+    reference operator*() { return (*vector_ptr)[index]; }
+    const reference operator*() const { return (*vector_ptr)[index]; }
+
+    pointer operator->() { return &(*vector_ptr)[index]; }
+    const pointer operator->() const { return &(*vector_ptr)[index]; }
+
+    SafeVectorIterator& operator++() { ++index; return *this; }
+    SafeVectorIterator operator++(int) { return SafeVectorIterator(vector_ptr, index++); }
+
+    SafeVectorIterator& operator--() { --index; return *this; }
+    SafeVectorIterator operator--(int) { return SafeVectorIterator(vector_ptr, index--); }
+
+    template<class Integer>
+    SafeVectorIterator& operator+=(Integer rhs) {
+        index += rhs;
+        return *this;
+    }
+
+    template<class Integer>
+    SafeVectorIterator& operator-=(Integer rhs) {
+        index -= rhs;
+        return *this;
+    }
+
+    const vector_type *get_vector_ptr() const { return vector_ptr; }
+
+    size_type get_index() const { return index; }
+
+    typename vector_type::value_type foo() { return typename V::value_type(); }
+
+private:
+    vector_type *vector_ptr;
+    size_type index;
+};
+
+template <class V>
+bool operator==(const SafeVectorIterator<V>& lhs, const SafeVectorIterator<V>& rhs) {
+    assert(lhs.get_vector_ptr() && lhs.get_vector_ptr() == rhs.get_vector_ptr());
+    return lhs.get_index() == rhs.get_index();
+}
+
+template <class V>
+bool operator!=(const SafeVectorIterator<V>& lhs, const SafeVectorIterator<V>& rhs) {
+    assert(lhs.get_vector_ptr() && lhs.get_vector_ptr() == rhs.get_vector_ptr());
+    return lhs.get_index() != rhs.get_index();
+}
+
+template <class V>
+bool operator<(const SafeVectorIterator<V>& lhs, const SafeVectorIterator<V>& rhs) {
+    assert(lhs.get_vector_ptr() && lhs.get_vector_ptr() == rhs.get_vector_ptr());
+    return lhs.get_index() < rhs.get_index();
+}
+
+template <class V>
+bool operator<=(const SafeVectorIterator<V>& lhs, const SafeVectorIterator<V>& rhs) {
+    assert(lhs.get_vector_ptr() && lhs.get_vector_ptr() == rhs.get_vector_ptr());
+    return lhs.get_index() <= rhs.get_index();
+}
+
+template <class V>
+bool operator>(const SafeVectorIterator<V>& lhs, const SafeVectorIterator<V>& rhs) {
+    assert(lhs.get_vector_ptr() && lhs.get_vector_ptr() == rhs.get_vector_ptr());
+    return lhs.get_index() > rhs.get_index();
+}
+
+template <class V>
+bool operator>=(const SafeVectorIterator<V>& lhs, const SafeVectorIterator<V>& rhs) {
+    assert(lhs.get_vector_ptr() && lhs.get_vector_ptr() == rhs.get_vector_ptr());
+    return lhs.get_index() >= rhs.get_index();
+}
+
+template <class V, class Integer>
+SafeVectorIterator<V> operator+(const SafeVectorIterator<V>& lhs, Integer rhs) {
+    return SafeVectorIterator<V>(lhs.get_vector_ptr(), lhs.get_index() + rhs);
+}
+
+template <class V, class Integer>
+SafeVectorIterator<V> operator+(Integer lhs, const SafeVectorIterator<V>& rhs) {
+    return SafeVectorIterator<V>(rhs.get_vector_ptr(), lhs + rhs.get_index());
+}
+
+template <class V, class Integer>
+SafeVectorIterator<V> operator-(const SafeVectorIterator<V>& lhs, Integer rhs) {
+    return SafeVectorIterator<V>(lhs.get_vector_ptr(), lhs.get_index() - rhs);
+}
+
+template <class V, class Integer>
+SafeVectorIterator<V> operator-(Integer lhs, const SafeVectorIterator<V>& rhs) {
+    return SafeVectorIterator<V>(rhs.get_vector_ptr(), lhs - rhs.get_index());
+}
+
+template <class V>
+typename SafeVectorIterator<V>::difference_type operator-(
+        const SafeVectorIterator<V>& lhs,
+        const SafeVectorIterator<V>& rhs)
+{
+    assert(lhs.get_vector_ptr() && lhs.get_vector_ptr() == rhs.get_vector_ptr());
+    return SafeVectorIterator<V>(lhs.get_vector_ptr(), lhs.get_index() - rhs.get_index());
+}
+
+#define LEMON_DEFINE_BINARY_OPERATOR(op) \
+    IndexType& operator op ## =(const IndexType& rhs) { \
+        assert(vector_ptr && vector_ptr == rhs.vector_ptr); \
+        index op ## = rhs.index; \
+        return *this; \
+    } \
+    IndexType& operator op ## =(size_type rhs) { \
+        assert(vector_ptr); \
+        index op ## = rhs; \
+        return *this; \
+    } \
+    IndexType operator op(const IndexType& rhs) { \
+        assert(vector_ptr && vector_ptr == rhs.vector_ptr); \
+        IndexType nrv(*this); \
+        nrv op ## = rhs; \
+        return nrv; \
+    } \
+    IndexType operator op(size_type rhs) { \
+        IndexType nrv(*this); \
+        nrv op ## = rhs; \
+        return nrv; \
+    }
+
+#define LEMON_DEFINE_COMP_OPERATOR(op) \
+    template<class V> \
+    bool operator op(const IndexType<V>& lhs, const IndexType<V>& rhs) { \
+        assert(lhs.get_vector_ptr() && lhs.get_vector_ptr() == rhs.get_vector_ptr()); \
+        return lhs.get_index() op rhs.get_index(); \
+    } \
+    template<class V> \
+    bool operator op(typename IndexType<V>::size_type lhs, const IndexType<V>& rhs) { \
+        assert(rhs.get_vector_ptr()); \
+        return lhs op rhs.get_index(); \
+    } \
+    template<class V> \
+    bool operator op(const IndexType<V>& lhs, typename IndexType<V>::size_type rhs) { \
+        assert(lhs.get_vector_ptr()); \
+        return lhs.get_index() op rhs; \
+    }
+
+#define LEMON_DEFINE_INC_OPERATOR(op) \
+    IndexType& operator op() { \
+        assert(vector_ptr); \
+        op index; \
+        return *this; \
+    } \
+    IndexType operator op(int) { \
+        assert(vector_ptr); \
+        IndexType res(*this); \
+        op *this; \
+        return res; \
+    }
+
+template<class V>
+struct IndexType {
+    typedef V vector_type;
+    typedef typename V::size_type size_type;
+
+    IndexType() : index(), vector_ptr() {}
+    IndexType(const vector_type *vector_ptr, size_type index) : vector_ptr(vector_ptr), index(index) {}
+
+    size_type get_index() const { return index; }
+    const vector_type *get_vector_ptr() const { return vector_ptr; }
+
+    operator size_type() const { return index; }
+
+    LEMON_DEFINE_BINARY_OPERATOR(+);
+    LEMON_DEFINE_BINARY_OPERATOR(-);
+    LEMON_DEFINE_BINARY_OPERATOR(*);
+    LEMON_DEFINE_BINARY_OPERATOR(/);
+    LEMON_DEFINE_BINARY_OPERATOR(%);
+    LEMON_DEFINE_BINARY_OPERATOR(|);
+    LEMON_DEFINE_BINARY_OPERATOR(&);
+    LEMON_DEFINE_BINARY_OPERATOR(^);
+
+    LEMON_DEFINE_INC_OPERATOR(++);
+    LEMON_DEFINE_INC_OPERATOR(--);
+
+private:
+    const vector_type *vector_ptr;
+    size_type index;
+};
+
+LEMON_DEFINE_COMP_OPERATOR(==);
+LEMON_DEFINE_COMP_OPERATOR(!=);
+LEMON_DEFINE_COMP_OPERATOR(<);
+LEMON_DEFINE_COMP_OPERATOR(>);
+LEMON_DEFINE_COMP_OPERATOR(<=);
+LEMON_DEFINE_COMP_OPERATOR(>=);
+
+#undef LEMON_DEFINE_INC_OPERATOR
+#undef LEMON_DEFINE_BINARY_OPERATOR
+#undef LEMON_DEFINE_COMP_OPERATOR
+
+template<class T, class Alloc = std::allocator<T> >
+class SafeVector {
+public:
+    typedef std::vector<T, Alloc> vector_type;
+    typedef typename vector_type::value_type value_type;
+    typedef typename vector_type::allocator_type allocator_type;
+    typedef typename vector_type::reference reference;
+    typedef typename vector_type::const_reference const_reference;
+    typedef typename vector_type::pointer pointer;
+    typedef typename vector_type::const_pointer const_pointer;
+    typedef typename vector_type::iterator iterator;
+    typedef typename vector_type::const_iterator const_iterator;
+    typedef typename vector_type::reverse_iterator reverse_iterator;
+    typedef typename vector_type::const_reverse_iterator const_reverse_iterator;
+
+    //TODO possible improvement: permanent_const_iterator, permanent_reverse_iterator, etc
+    typedef SafeVectorIterator<vector_type> permanent_iterator;
+
+    typedef typename vector_type::difference_type difference_type;
+    typedef typename vector_type::size_type size_type;
+
+#ifdef NDEBUG
+    typedef size_type index_type;
+#else
+    typedef IndexType<vector_type> index_type;
+#endif
+
+    explicit SafeVector(const allocator_type& alloc = allocator_type()) :
+        vector(alloc) {}
+
+    explicit SafeVector(size_type n, const value_type& val = value_type(),
+            const allocator_type& alloc = allocator_type()) :
+        vector(n, val, alloc) {}
+
+    template <class InputIterator>
+    SafeVector(InputIterator first, InputIterator last,
+            const allocator_type& alloc = allocator_type()) :
+        vector(first, last, alloc) {}
+
+    SafeVector(const vector_type& other) : vector(other) {}
+    SafeVector(const SafeVector& other) : vector(other.vector) {}
+
+    SafeVector& operator=(const vector_type& other) {
+        vector = other;
+        return *this;
+    }
+
+    SafeVector& operator=(const SafeVector& other) {
+        vector = other.vector;
+        return *this;
+    }
+
+    index_type get_index(size_type index) {
+#ifdef NDEBUG
+        return index;
+#else
+        return index_type(&vector, index);
+#endif
+    }
+
+    iterator begin() { return vector.begin(); }
+    const_iterator begin() const { return vector.begin(); }
+
+    iterator end() { return vector.end(); }
+    const_iterator end() const { return vector.end(); }
+
+    reverse_iterator rbegin() { return vector.rbegin(); }
+    const_reverse_iterator rbegin() const { return vector.rbegin(); }
+
+    reverse_iterator rend() { return vector.rend(); }
+    const_reverse_iterator rend() const { return vector.rend(); }
+
+    permanent_iterator pbegin() { return permanent_iterator(&vector, 0); }
+    permanent_iterator pbegin() const { return permanent_iterator(vector, 0); }
+
+    permanent_iterator pend() { return permanent_iterator(&vector, size()); }
+    permanent_iterator pend() const { return permanent_iterator(&vector, size()); }
+
+    size_type size() const { return vector.size(); }
+    size_type max_size() const { return vector.max_size(); }
+
+    void resize(size_type n, value_type val = value_type()) {
+        vector.resize(n, val);
+    }
+
+    size_type capacity() const { return vector.capacity(); }
+
+    bool empty() const { return vector.empty(); }
+
+    void reserve(size_type n) { return vector.reserve(n); }
+
+    reference operator[](size_type n) { return vector[n]; }
+    const_reference operator[](size_type n) const { return vector[n]; }
+#ifndef NDEBUG
+    reference operator[](index_type n) {
+       assert(n.get_vector_ptr() == &vector);
+       assert(n.get_index() < size());
+       return vector[n.get_index()];
+    }
+    const_reference operator[](index_type n) const {
+       assert(n.get_vector_ptr() == &vector);
+       assert(n.get_index() < size());
+       return vector[n.get_index()];
+    }
+#endif
+
+    reference at(size_type n) { return vector.at(n); }
+    const_reference at(size_type n) const { return vector.at(n); }
+#ifndef NDEBUG
+    reference at(index_type n) {
+       assert(n.get_vector_ptr() == &vector);
+       return vector.at(n.get_index());
+    }
+    const_reference at(index_type n) const {
+       assert(n.get_vector_ptr() == &vector);
+       return vector.at(n.get_index());
+    }
+#endif
+
+    reference front() { return vector.front(); }
+    const_reference front() const { return vector.front(); }
+
+    reference back() { return vector.back(); }
+    const_reference back() const { return vector.back(); }
+
+    template <class InputIterator>
+    void assign(InputIterator first, InputIterator last) {
+        vector.assign(first, last);
+    }
+
+    void assign(size_type n, const value_type& val) {
+        vector.assign(n, val);
+    }
+
+    void push_back(const value_type& val) { vector.push_back(val); }
+
+    void pop_back() { vector.pop_back(); }
+
+    iterator insert(iterator position, const value_type& val) {
+        return vector.insert(position, val);
+    }
+
+    void insert(iterator position, size_type n, const value_type& val) {
+        return vector.insert(position, n, val);
+    }
+
+    template <class InputIterator>
+    void insert(iterator position, InputIterator first, InputIterator last) {
+        vector.insert(position, first, last);
+    }
+
+    iterator erase(iterator position) { return vector.erase(position); }
+
+    iterator erase(iterator first, iterator last) {
+        return vector.erase(first, last);
+    }
+
+    void swap(SafeVector& other) {
+        vector.swap(other.vector);
+    }
+
+    void clear() { vector.clear(); }
+
+    allocator_type get_allocator() const { return vector.get_allocator(); }
+
+    vector_type& get_vector() { return vector; }
+    const vector_type& get_vector() const { return vector; }
+
+private:
+    vector_type vector;
+};
+
+template <class T, class Alloc>
+bool operator==(const SafeVector<T, Alloc>& lhs, const SafeVector<T, Alloc>& rhs) {
+    return lhs.get_vector() == rhs.get_vector();
+}
+
+template <class T, class Alloc>
+bool operator!=(const SafeVector<T, Alloc>& lhs, const SafeVector<T, Alloc>& rhs) {
+    return lhs.get_vector() != rhs.get_vector();
+}
+
+template <class T, class Alloc>
+bool operator<(const SafeVector<T, Alloc>& lhs, const SafeVector<T, Alloc>& rhs) {
+    return lhs.get_vector() < rhs.get_vector();
+}
+
+template <class T, class Alloc>
+bool operator<=(const SafeVector<T, Alloc>& lhs, const SafeVector<T, Alloc>& rhs) {
+    return lhs.get_vector() <= rhs.get_vector();
+}
+
+template <class T, class Alloc>
+bool operator>(const SafeVector<T, Alloc>& lhs, const SafeVector<T, Alloc>& rhs) {
+    return lhs.get_vector() > rhs.get_vector();
+}
+
+template <class T, class Alloc>
+bool operator>=(const SafeVector<T, Alloc>& lhs, const SafeVector<T, Alloc>& rhs) {
+    return lhs.get_vector() >= rhs.get_vector();
+}
+
+
+}
+
+#endif
diff -r 5de6a70446f6 test/CMakeLists.txt
--- a/test/CMakeLists.txt	Wed Jul 09 14:41:36 2014 +0200
+++ b/test/CMakeLists.txt	Tue Nov 25 14:52:27 2014 +0100
@@ -46,6 +46,7 @@
   min_cost_flow_test
   min_mean_cycle_test
   nagamochi_ibaraki_test
+  safe_vector_test
   path_test
   planarity_test
   radix_sort_test
diff -r 5de6a70446f6 test/safe_vector_test.cc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/safe_vector_test.cc	Tue Nov 25 14:52:27 2014 +0100
@@ -0,0 +1,55 @@
+
+#ifdef NDEBUG
+#undef NDEBUG
+#endif
+
+#include <lemon/safe_vector.h>
+#include "test_tools.h"
+
+using namespace lemon;
+
+int main() {
+
+    {
+        SafeVector<int> v;
+        for (int i = 0; i < 10; ++i) {
+            v.push_back(i);
+        }
+
+        int i = 0;
+        for (SafeVector<int>::permanent_iterator it = v.pbegin(); it != v.pend(); ++it) {
+            check(*it == i++, "Content check failed");
+        }
+    }
+    {
+        SafeVector<std::string> v;
+        for (unsigned i = 0; i < 10; ++i) {
+            v.push_back(std::string(i, '*'));
+        }
+
+        unsigned i = 0;
+        for (SafeVector<std::string>::permanent_iterator it = v.pbegin(); it < v.pend(); it += 1) {
+            check(it->size() == i++, "Content check failed");
+        }
+    }
+    {
+        SafeVector<int> v;
+        for (int i = 0; i < 10; ++i) {
+            v.push_back(i);
+        }
+
+        for (SafeVector<int>::index_type i = v.get_index(0); i < v.size(); ++i) {
+            check(static_cast<SafeVector<int>::size_type>(v[i]) == i, "Content check failed");
+        }
+    }
+    {
+        SafeVector<int> v;
+        for (int i = 0; i < 10; ++i) {
+            v.push_back(i);
+        }
+
+        for (SafeVector<int>::index_type i = v.get_index(0); i != v.size(); i += 1) {
+            check(static_cast<SafeVector<int>::size_type>(v.at(i)) == i, "Content check failed");
+        }
+    }
+}
