M
Michael Hopkins
Hi all
I want to create a std::vector that goes from 1 to n instead of 0 to n-1.
The only change this will have is in loops and when the vector returns
positions of elements etc. I am calling this uovec at the moment (for
Unit-Offset VECtor). I want the class to respond correctly to all usage of
STL containers and algorithms so that it is a transparent replacement for
std:vector.
The options seems to be:
1) deriving publicly from std::vector and then define operator(), but I
believe that std::vector is not meant to be used as a base class so no
virtual destructor (and possibly other gotchas) though in this case I
wouldn't need to store any members in the derived class so maybe this would
make no difference?
2) store a std::vector inside and use it as necessary - this appears to be
the preferred option.
3) other? Deriving privately from std::vector and an interface?
In any case I suspect housekeeping will be required to keep STL containers
and algorithms happy.
A couple of years ago I was asking these questions on the list and got
several helpful replies but got distracted by other tasks and dropped C++.
Am now back (and better prepared) and I was interested in a critique of this
first attempt. It uses (2) but I'm not sure if all the required STL
behaviour is covered so I have the getout clause of direct access to the
contained std::vector. I would prefer to avoid doing this.
template <class T>
/////////////////////////////////
// uovec - a std:vector<T> but with unit-offset via operator ()
// can add other stuff to make it exactly like std::vector
// can call v.foo() or use vref() if necessary but not very elegant
/////////////////////////////////
class uovec {
typedef std::vector<T> vT;
static const iter offset = 1;
vT v;
public:
// simple constructors
uovec ( const iter s ) : v( s ) {}
uovec ( const iter s, const T fill ) : v( s, fill ) {}
// copy constructors and assignments will be required but not given here
// access from 1 to n
inline T& operator() ( const iter i ) { return v[i-offset]; }
inline const T& operator() ( const iter i ) const { return v[i-offset]; }
inline vT& vref () { return v; } // return reference to v in
case complicated STL required... nasty
inline const vT& vref () const { return v; } // return const reference to
const v
// vector iterators
typename vT::iterator begin() { return v.begin(); }
typename vT::iterator end() { return v.end(); }
typename vT::const_iterator begin() const { return v.begin(); }
typename vT::const_iterator end() const { return v.end(); }
typename vT::reverse_iterator rbegin() { return v.rbegin(); }
typename vT::reverse_iterator rend() { return v.rend(); }
typename vT::const_reverse_iterator rbegin() const { return v.rbegin(); }
typename vT::const_reverse_iterator rend() const { return v.rend(); }
};
Michael
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
_/ _/ _/_/_/ Hopkins Research Ltd
_/ _/ _/ _/
_/_/_/_/ _/_/_/ http://www.hopkins-research.com/
_/ _/ _/ _/
_/ _/ _/ _/ 'touch the future'
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
I want to create a std::vector that goes from 1 to n instead of 0 to n-1.
The only change this will have is in loops and when the vector returns
positions of elements etc. I am calling this uovec at the moment (for
Unit-Offset VECtor). I want the class to respond correctly to all usage of
STL containers and algorithms so that it is a transparent replacement for
std:vector.
The options seems to be:
1) deriving publicly from std::vector and then define operator(), but I
believe that std::vector is not meant to be used as a base class so no
virtual destructor (and possibly other gotchas) though in this case I
wouldn't need to store any members in the derived class so maybe this would
make no difference?
2) store a std::vector inside and use it as necessary - this appears to be
the preferred option.
3) other? Deriving privately from std::vector and an interface?
In any case I suspect housekeeping will be required to keep STL containers
and algorithms happy.
A couple of years ago I was asking these questions on the list and got
several helpful replies but got distracted by other tasks and dropped C++.
Am now back (and better prepared) and I was interested in a critique of this
first attempt. It uses (2) but I'm not sure if all the required STL
behaviour is covered so I have the getout clause of direct access to the
contained std::vector. I would prefer to avoid doing this.
template <class T>
/////////////////////////////////
// uovec - a std:vector<T> but with unit-offset via operator ()
// can add other stuff to make it exactly like std::vector
// can call v.foo() or use vref() if necessary but not very elegant
/////////////////////////////////
class uovec {
typedef std::vector<T> vT;
static const iter offset = 1;
vT v;
public:
// simple constructors
uovec ( const iter s ) : v( s ) {}
uovec ( const iter s, const T fill ) : v( s, fill ) {}
// copy constructors and assignments will be required but not given here
// access from 1 to n
inline T& operator() ( const iter i ) { return v[i-offset]; }
inline const T& operator() ( const iter i ) const { return v[i-offset]; }
inline vT& vref () { return v; } // return reference to v in
case complicated STL required... nasty
inline const vT& vref () const { return v; } // return const reference to
const v
// vector iterators
typename vT::iterator begin() { return v.begin(); }
typename vT::iterator end() { return v.end(); }
typename vT::const_iterator begin() const { return v.begin(); }
typename vT::const_iterator end() const { return v.end(); }
typename vT::reverse_iterator rbegin() { return v.rbegin(); }
typename vT::reverse_iterator rend() { return v.rend(); }
typename vT::const_reverse_iterator rbegin() const { return v.rbegin(); }
typename vT::const_reverse_iterator rend() const { return v.rend(); }
};
Michael
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
_/ _/ _/_/_/ Hopkins Research Ltd
_/ _/ _/ _/
_/_/_/_/ _/_/_/ http://www.hopkins-research.com/
_/ _/ _/ _/
_/ _/ _/ _/ 'touch the future'
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/