By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,444 Members | 3,182 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,444 IT Pros & Developers. It's quick & easy.

partial specialization on std::vector

P: n/a
i want to create a vector of pointer s.t. it can handle new and delete
but also have std::vector interface

can i implement by partial specialization and inherence like follow ?

#include <vector>
#include <algorithm>

template <typename T>
struct delete_ptr {
void operator() (T * p) {
delete p;
}
};

template<typename T>
class auto_vector<T *: public std::vector<T *{
public:
typedef std::vector<T *Base;
~auto_vector() {
clear();
}

void clear() {
std::for_each(begin(), end(), delete_ptr<T>());
Base::clear();
}

void push_back(const T *p) {
T* tmp = new T(*p)
Base::push_back(tmp);
}
};

Oct 29 '06 #1
Share this Question
Share on Google+
6 Replies


P: n/a
<lo*****@gmail.comwrote in message
news:11**********************@b28g2000cwb.googlegr oups.com
i want to create a vector of pointer s.t. it can handle new and delete
but also have std::vector interface

can i implement by partial specialization and inherence like follow ?

#include <vector>
#include <algorithm>

template <typename T>
struct delete_ptr {
void operator() (T * p) {
delete p;
}
};

template<typename T>
class auto_vector<T *: public std::vector<T *{
public:
typedef std::vector<T *Base;
~auto_vector() {
clear();
}

void clear() {
std::for_each(begin(), end(), delete_ptr<T>());
Base::clear();
}

void push_back(const T *p) {
T* tmp = new T(*p)
Base::push_back(tmp);
}
};
I suggest you might like to look at the Boost Pointer Containers:

http://www.boost.org/libs/ptr_contai...container.html
--
John Carson
Oct 29 '06 #2

P: n/a

lo*****@gmail.com wrote:
i want to create a vector of pointer s.t. it can handle new and delete
but also have std::vector interface

can i implement by partial specialization and inherence like follow ?

#include <vector>
#include <algorithm>

template <typename T>
struct delete_ptr {
void operator() (T * p) {
delete p;
}
};

template<typename T>
class auto_vector<T *: public std::vector<T *{
public:
typedef std::vector<T *Base;
~auto_vector() {
clear();
}

void clear() {
std::for_each(begin(), end(), delete_ptr<T>());
Base::clear();
}

void push_back(const T *p) {
T* tmp = new T(*p)
Base::push_back(tmp);
}
};
The stl containers are not designed to be inherited from ( no virtual
destructors ).
Besides, the container you are trying to code is_not a std::vector, it
looks like a std::vector.
What if someone copies that container?
What if the template parameter is a pointer?
I'ld suggest smart pointers as a better alternative to raw allocations.

#include <iostream>
#include <ostream>
#include <vector>
#include <boost/shared_ptr.hpp>

template< typename T >
class auto_vector
{
typedef boost::shared_ptr< T SharedPtrT;
std::vector< SharedPtrT m_vp;
typedef typename std::vector< SharedPtrT >::const_iterator VCIter;
public:
/* ctors */
auto_vector() : m_vp() { }
auto_vector(const auto_vector& r_copy)
{
for(VCIter viter = r_copy.m_vp.begin();
viter != r_copy.m_vp.end(); ++viter)
{
m_vp.push_back( SharedPtrT( new T(*(*viter)) ) );
}
}
/* member functions */
void push_back( const T& t )
{
m_vp.push_back( SharedPtrT( new T(t) ) );
}
void clear()
{
m_vp.clear();
}
/* friends */
friend
std::ostream&
operator<<( std::ostream& os, const auto_vector& r_av )
{
for(VCIter viter = r_av.m_vp.begin();
viter != r_av.m_vp.end(); ++viter)
{
os << *(*viter) << "\n";
}
return os;
}
};

int main()
{
auto_vector< int avn;
for( int i = 0; i < 2; ++i)
{
avn.push_back( i );
}
std::cout << avn << std::endl;

return 0;
}

and the ouput using a simple struct instead of int:
N(int) // temp
N(const N& copy) // push_back
~N() // temp
N(int) // temp
N(const N& copy) // push_back
~N() // temp
0
1
~N()
~N()

Oct 29 '06 #3

P: n/a
Salt_Peter wrote:
....
The stl containers are not designed to be inherited from ( no virtual
destructors ).
All your other suggestions aside. I think the consensus is that "no
virtual destructor" is not a reason for "not being designed" to be
inherited.

A virtual destructor is only needed if you destroy your object from a
super class. Most people agree that that usually means if you have any
virtual methods - but not necessarily so. For example, I just posted
code on a different thread where objects are created statically yet they
have virtual methods.

It is perfectly ok to inherit from std::vector and yes there are
limitations but if those limitations are not an issue, the world is good.
Oct 29 '06 #4

P: n/a
lo*****@gmail.com wrote:
i want to create a vector of pointer s.t. it can handle new and delete
but also have std::vector interface

can i implement by partial specialization and inherence like follow ?

#include <vector>
#include <algorithm>

template <typename T>
struct delete_ptr {
void operator() (T * p) {
delete p;
}
};

template<typename T>
class auto_vector<T *: public std::vector<T *{
public:
typedef std::vector<T *Base;
~auto_vector() {
clear();
}

void clear() {
std::for_each(begin(), end(), delete_ptr<T>());
Base::clear();
}

void push_back(const T *p) {
T* tmp = new T(*p)
Base::push_back(tmp);
}
};
This is a strange design:

a) the vector goes through some length to make copies in the push_back
method, however allows for ordinary access through operaror=. This is quite
inconsistent.

b) When the copy constructor of the vector is used, the result will be two
vectors both owning the pointers. When the first vector is destroyed, the
second becomes invalid and any call to its destructor becomes undefined
behavior.

c) The way the push_back method is implemented, it does not support
polymorphic pointers:

T* tmp = new T (*p);

will slice should p actually point to an object of type derived from T.
What problem are you trying to solve? Why do you want a vector of pointers
and not of objects in the first place: if it is to support polymorphism,
but you want to preserve copy semantics for the container, then you might
want to look into smart-pointers with copy semantics. Several have been
posted in this group; some of them also define comparison in terms of the
pointees. Then, you could just use std::vector< copy_ptr<T and even sort
would do the RightThing(tm). Google for copy_ptr<or clone_ptr<in the
archive of this group and its moderated twin.
Best

Kai-Uwe Bux
Oct 29 '06 #5

P: n/a

Gianni Mariani wrote:
Salt_Peter wrote:
...
The stl containers are not designed to be inherited from ( no virtual
destructors ).

All your other suggestions aside. I think the consensus is that "no
virtual destructor" is not a reason for "not being designed" to be
inherited.

A virtual destructor is only needed if you destroy your object from a
super class. Most people agree that that usually means if you have any
virtual methods - but not necessarily so. For example, I just posted
code on a different thread where objects are created statically yet they
have virtual methods.

It is perfectly ok to inherit from std::vector and yes there are
limitations but if those limitations are not an issue, the world is good.
Its not the lack of the virtual destructor alone that should discourage
inheriting from a container like the std::vector in a case like this
one. In fact its a secondary issue. Perhaps i should have made a
cleaner point of it.

Public inheritance forces the coder to override the entire interface
(operator[], assignment, at(), etc). What happens if an unsuspecting
user of the code tries to iterate through the elements, which are
actually pointers? What if one attempts to presize the container using
a vector's ctor? What if a common algorithm (swap, count_if, replace,
remove_if, sort, min, nth_element, etc) is applied to the container?
And so on.
Clearly, its no longer a std::vector, is it?

Oct 29 '06 #6

P: n/a
Salt_Peter wrote:
>
Gianni Mariani wrote:
>Salt_Peter wrote:
...
The stl containers are not designed to be inherited from ( no virtual
destructors ).

All your other suggestions aside. I think the consensus is that "no
virtual destructor" is not a reason for "not being designed" to be
inherited.

A virtual destructor is only needed if you destroy your object from a
super class. Most people agree that that usually means if you have any
virtual methods - but not necessarily so. For example, I just posted
code on a different thread where objects are created statically yet they
have virtual methods.

It is perfectly ok to inherit from std::vector and yes there are
limitations but if those limitations are not an issue, the world is good.

Its not the lack of the virtual destructor alone that should discourage
inheriting from a container like the std::vector in a case like this
one. In fact its a secondary issue. Perhaps i should have made a
cleaner point of it.

Public inheritance forces the coder to override the entire interface
(operator[], assignment, at(), etc).
Using public innheritance, only the parts that need to be changed in order
to ensure the proper semantics need to be overwritten. Unfortunately, if
the OP wants deep-copy-semantics for the vector entries, as indicated by
his implementation of the push_back() method, this would entail
reimplementing the entire iterator type. I conclude, you have a valid point
here. However, this effort is not a consequence of public inheritance: all
other methods will not safe any work.

What happens if an unsuspecting
user of the code tries to iterate through the elements, which are
actually pointers?
The user should get a compile time error.
What if one attempts to presize the container using
a vector's ctor?
Huh? Could you provide a code snippet: I do not quite understand what you
have in mind.
What if a common algorithm (swap, count_if, replace,
remove_if, sort, min, nth_element, etc) is applied to the container?
And so on.
Clearly, its no longer a std::vector, is it?
Of course it *is* a std::vector. However, it is not a std::vector<Tbut a
std::vector<T*>. The OP said he wanted a vector of pointers. He proposed:

template<typename T>
class auto_vector<T *: public std::vector<T *{
public:
...
};

To answer your what-if questions: std::sort will sort it happily using
less<T*>, remove_if() could be used to eliminate 0-pointers, and so on.
Since the OP explicitly stated he wants a vector of pointers, this might
even be what he expects. Also, it clearly is consistent with what
std::vector<T*would do. Thus, auto_vector is a std::vector<T*>.
Now, whether a vector of pointers is a good thing to use, is a different
matter.
Best

Kai-Uwe Bux
Oct 29 '06 #7

This discussion thread is closed

Replies have been disabled for this discussion.