I have repeatedly read that inheriting from STL containers is a Bad Thing.
(I know what the reasons behind this are, that's not my question.)
Keeping the above in mind, what is the proper way to extend the functionality of a container?
For example, if I want a vector
-like container that automatically resizes when the argument of operator[]
is greater than or equal to the size of the container, what would I do?
To me, the most obvious solution in C++11 is:
template<class T, class A = std::allocator<T> >
class auto_vector : public std::vector<T, A>
{
typedef std::vector<T, A> base_type;
public:
using base_type::vector;
typename base_type::reference operator[](typename base_type::size_type n)
// I don't need const version, so I'll just ignore it here
{
if (n >= this->base_type::size())
{ this->base_type::resize(n + 1); }
return this->base_type::operator[](n);
}
};
In C++03, it would be:
template<class T, class A = std::allocator<T> >
class auto_vector : public std::vector<T, A>
{
typedef std::vector<T, A> base_type;
public:
explicit auto_vector(
typename base_type::allocator_type const &alloc =
typename base_type::allocator_type())
: base_type(alloc) { }
explicit auto_vector(
typename base_type::size_type n,
value_type const &val = value_type(),
typename base_type::allocator_type const &alloc =
typename base_type::allocator_type())
: base_type(n, val, alloc) { }
template<class InIt>
auto_vector(InIt f, InIt l, typename base_type::allocator_type const &alloc =
typename base_type::allocator_type())
: base_type(f, l, alloc) { }
auto_vector(auto_vector const &v) : base_type(v) { }
typename base_type::reference operator[](typename base_type::size_type n)
// I don't need const version
{
if (n >= this->base_type::size())
{ this->base_type::resize(n + 1); }
return this->base_type::operator[](n);
}
};
Both of these are bad practice because they inherit from std::vector
.