pandorafms/extras/anytermd/libpbe/include/strector.hh

94 lines
3.2 KiB
C++

// include/strector.hh
// This file is part of libpbe; see http://svn.chezphil.org/libpbe/
// (C) 2008 Philip Endecott
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef libpbe_strector_hh
#define libpbe_strector_hh
// strector: stretchy-vector
// -------------------------
//
// Provides a vector which stretches when new elements are accessed
// using operator[].
//
// Since the stretch may cause the vector to re-allocate, operator[]
// on a mutable strector invalidates iterators, references and pointers
// to its elements unless the index is less than capacity().
//
// What should operator[] do for a const strector when you access a
// beyond-the-end element? It can't stretch the vector. It could be
// undefined (like vector). It could throw. It could return a default
// T by value - but then it would have to return by value in all cases.
// The option that I've chosen is to return a const reference to a static
// T. This is broken if you try to compare addresses of elements. It
// is also broken if you expected the reference to change when you wrote
// to that element via a mutable reference to the strector, but that would
// be broken anyway unless size() < index < capacity() due to the
// iterator-invalidation rules. The use of a static may also have
// thread-safety problems.
//
// An additional optional constructor parameter allows you to specify a value
// used for new elements when the vector is resized during operator[] and
// when a beyond-the-end element is read as above.
#include <vector>
namespace pbe {
template < typename T, typename ALLOC=std::allocator<T> >
class strector: public std::vector<T,ALLOC> {
typedef std::vector<T,ALLOC> base_t;
const T default_t;
public:
// Same ctors as std::vector:
strector() {}
strector(typename base_t::size_type n): base_t(n) {}
strector(typename base_t::size_type n, const T& t): base_t(n,t), default_t(t) {}
// The copy-ctor takes a base_t, so we can copy from another strector or
// from a compatible std::vector:
strector(const base_t& other): base_t(other) {}
template <typename iter>
strector(iter first, iter last): base_t(first,last) {}
// Additional ctor to specify default_t:
explicit strector(const T& default_t_): default_t(default_t_) {}
typename base_t::reference operator[](typename base_t::size_type n) {
if (n>=base_t::size()) {
base_t::resize(n+1,default_t);
}
return base_t::operator[](n);
}
typename base_t::const_reference operator[](typename base_t::size_type n) const {
if (n>=base_t::size()) {
return default_t;
}
return base_t::operator[](n);
}
};
};
#endif