Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Container elements with const members

Reply
Thread Tools

Container elements with const members

 
 
Nobody
Guest
Posts: n/a
 
      04-21-2004
The requirement that STL container elements have to be assignable is causing
me a problem.
Consider a class X which contains both const and non-const data members:

class X
{
public:
X(const std::string &rStrId, int x) : m_strId(strId), m_x(x)
{
}

private:
X& operator=(const X &rhs); // not allowed
X(const X& rhs); // not allowed

const std::string m_strId;
int m_x;
};

I know that because I have the data member, m_strId, declared as *const*, it
means that I cannot assign to it. This was OK as I didn't need to and
therefore made it private with no implementation.

Then I decided that I needed to have an STL vector of Xs.

X x(std::string("hello"), 43);
std::vector<X > xVector;
....
xVector.push_back(X(std::string("hello"), 43));

I know too that when using STL containers the standard says that the
contained objects must be copyable and assignable.

This is my dilemma. If I don't supply an assignment operator for X or I make
it private then it won't compile when I try to push an instance of X into
the vector.

I have considered the following options:

1) Make the string non const and let the compiler generate the assignment
operator. I don't want to do this as each instance of X is required to have
a unique string identifier, m_strId, which will not change throughout the
lifetime of the object.

2) Provide an assignment operator that only assigns the non const int m_x.
This would allow the possibility of assigning one X object to another and
the result not being equal.

Which is the best option of the two? Are there any other alternatives I
haven't considered which are better?

TIA

RP


 
Reply With Quote
 
 
 
 
Siemel Naran
Guest
Posts: n/a
 
      04-21-2004
"Nobody" <(E-Mail Removed)> wrote in message news:E4Bhc.3313

> class X
> {
> public:
> X(const std::string &rStrId, int x) : m_strId(strId), m_x(x)
> {
> }
>
> private:
> X& operator=(const X &rhs); // not allowed
> X(const X& rhs); // not allowed
>
> const std::string m_strId;


> I know too that when using STL containers the standard says that the
> contained objects must be copyable and assignable.


> 1) Make the string non const and let the compiler generate the assignment
> operator. I don't want to do this as each instance of X is required to

have
> a unique string identifier, m_strId, which will not change throughout the
> lifetime of the object.


Yes, your design should reflect your business requirements, not the
technical requirements on STL containers.

> 2) Provide an assignment operator that only assigns the non const int m_x.
> This would allow the possibility of assigning one X object to another and
> the result not being equal.


Yes, this also violates your business requirement.

> Which is the best option of the two? Are there any other alternatives I
> haven't considered which are better?


Use a container of pointers to X. Remember to delete the pointed to objects
when the container goes out of scope.

You could try smart pointers, like so:

std::vector<boost::shared_ptr<X> > d_container;


 
Reply With Quote
 
 
 
 
Claudio Jolowicz
Guest
Posts: n/a
 
      04-21-2004
On Wed, 21 Apr 2004, Nobody wrote:

[snip]

>class X
>{
>public:
> X(const std::string &rStrId, int x) : m_strId(strId), m_x(x)
> {
> }
>
> private:
> X& operator=(const X &rhs); // not allowed
> X(const X& rhs); // not allowed
>
> const std::string m_strId;
> int m_x;
>};


[snip]

>X x(std::string("hello"), 43);
>std::vector<X > xVector;
>...
> xVector.push_back(X(std::string("hello"), 43));
>
>I know too that when using STL containers the standard says that the
>contained objects must be copyable and assignable.


[snip]

>I have considered the following options:
>
>1) Make the string non const and let the compiler generate the assignment
>operator. I don't want to do this as each instance of X is required to have
>a unique string identifier, m_strId, which will not change throughout the
>lifetime of the object.
>
>2) Provide an assignment operator that only assigns the non const int m_x.
>This would allow the possibility of assigning one X object to another and
>the result not being equal.
>
>Which is the best option of the two?


Neither option is correct if your code must guarantee that there is only
one instance for any string identifier, and the same string identifier
for a given object throughout the object's lifetime.

>Are there any other alternatives I
>haven't considered which are better?


Yes, store pointers in the vector. For example:

#include <vector>
#include <string>

class X
{
public:
X(const std::string &rStrId, int x)
: m_strId(rStrId), m_x(x)
{}

private:
X& operator=(const X &rhs); //not allowed
X(const X& rhs); //not allowed

const std::string m_strId;
int m_x;
};

class App
{
std::vector<X*> m_pvx;

public:
App()
: m_pvx()
{}

~App()
{
for (std::vector<X*>::iterator it = m_pvx.begin();
it != m_pvx.end();
++it)
delete *it;
}

void run()
{
m_pvx.push_back(new X(std::string("hello"), 43));
}
};

int main()
{
App().run();
}

--
Claudio Jolowicz
http://www.doc.ic.ac.uk/~cj603



 
Reply With Quote
 
Thorsten Ottosen
Guest
Posts: n/a
 
      04-21-2004
"Claudio Jolowicz" <(E-Mail Removed)> wrote in message
news(E-Mail Removed) .ac.uk...
| On Wed, 21 Apr 2004, Nobody wrote:

|
| Yes, store pointers in the vector. For example:

[snip]

|
| class App
| {
| std::vector<X*> m_pvx;

^^^^^^^^^^^^^^^^^^^^^^

highly non-recommended. Use vector< shared_ptr<X> >.

br

Thorsten


 
Reply With Quote
 
Siemel Naran
Guest
Posts: n/a
 
      04-22-2004
"Thorsten Ottosen" <(E-Mail Removed)> wrote in message
news:408703bd$0$20662
> "Claudio Jolowicz" <(E-Mail Removed)> wrote in message


>> std::vector<X*> m_pvx;

>
> highly non-recommended. Use vector< shared_ptr<X> >.


Highly non-recommended by who? I think Claudio's original solution is fine.
It uses less memory than your version (a counted_ptr is about twice the size
as a regular pointer, plus add memory for the actual integers), though
granted this may sometimes pale in comparison to the sizeof(X).

To save on the typing, it would be nice to generalize the idea to a template
class pointer_container<T> that holds a container<T*>, and whose destructor
deletes the items.


 
Reply With Quote
 
Dave Moore
Guest
Posts: n/a
 
      04-22-2004
"Siemel Naran" <(E-Mail Removed)> wrote in message news:<5NGhc.18257$(E-Mail Removed)>...

> To save on the typing, it would be nice to generalize the idea to a template
> class pointer_container<T> that holds a container<T*>, and whose destructor
> deletes the items.


Hmm .. aren't there ownership issues inherent to this idea? Who is to
say that the elements in the container belong to it? Couldn't the
pointer-elements have been initialized from already existing objects,
for example the elements of another container<T*>? It seems to me
that this would only really be useful in the context of the boost
smart-pointers, where ownership is already clear, IOW

shared_ptr_container<T> for container<shared_ptr<T> >, when the
elements will be owned by the container and
weak_ptr_container<T> for container<weak_ptr<T> > when they will not.

I suppose you could do a similar thing without boost as:

owned_ptr_container<T> // destructor deletes elements
view_ptr_container<T> // destructor doesn't delete elements

Dave Moore
 
Reply With Quote
 
Siemel Naran
Guest
Posts: n/a
 
      04-22-2004
"Dave Moore" <(E-Mail Removed)> wrote in message
> "Siemel Naran" <(E-Mail Removed)> wrote in message

news:<5NGhc.18257

> > To save on the typing, it would be nice to generalize the idea to a

template
> > class pointer_container<T> that holds a container<T*>, and whose

destructor
> > deletes the items.

>
> Hmm .. aren't there ownership issues inherent to this idea? Who is to
> say that the elements in the container belong to it? Couldn't the
> pointer-elements have been initialized from already existing objects,
> for example the elements of another container<T*>? It seems to me
> that this would only really be useful in the context of the boost
> smart-pointers, where ownership is already clear, IOW


Right, to make the intent clear we ought to name the container as
owned_pointer_container or something like that. But my intent was to not
use boost::shared_ptr in the implementation of my class.

> shared_ptr_container<T> for container<shared_ptr<T> >, when the
> elements will be owned by the container and
> weak_ptr_container<T> for container<weak_ptr<T> > when they will not.
>
> I suppose you could do a similar thing without boost as:
>
> owned_ptr_container<T> // destructor deletes elements
> view_ptr_container<T> // destructor doesn't delete elements


Yes, those are good names.


 
Reply With Quote
 
MikeB
Guest
Posts: n/a
 
      04-22-2004
"Siemel Naran" <(E-Mail Removed)> wrote in message
news:BEShc.10706$(E-Mail Removed)...

> owned_pointer_container or something like that. But my intent was to not
> use boost::shared_ptr in the implementation of my class.


I'm a bit lost here. In your first reply to the OP, you suggested that he

"...could try smart pointers, like so:
std::vector<boost::shared_ptr<X> > d_container;"

I assumed that in doing so you were actually recommending that he *should*
try boost::shared_ptr.

Rgds,
MikeB


 
Reply With Quote
 
Siemel Naran
Guest
Posts: n/a
 
      04-23-2004
"MikeB" <(E-Mail Removed)> wrote in message news:c698cf$ktn$1
> "Siemel Naran" <(E-Mail Removed)> wrote in message


> > owned_pointer_container or something like that. But my intent was to

not
> > use boost::shared_ptr in the implementation of my class.

>
> I'm a bit lost here. In your first reply to the OP, you suggested that he
>
> "...could try smart pointers, like so:
> std::vector<boost::shared_ptr<X> > d_container;"
>
> I assumed that in doing so you were actually recommending that he *should*
> try boost::shared_ptr.


I gave 2 possibilities, one vector<boost::shared_ptr<T>> and the other
essentially vector<T*>. The owned_pointer_container method is just
vector<T*> with an interface to delete the internal items.


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Resolving ambiguity between pointers to const and non-const members. Vladimir Menshakov C++ 1 05-15-2011 08:15 AM
number of distinct elements in a const container and iterating over the distinct elements Hicham Mouline C++ 1 04-11-2010 10:56 AM
const vector<A> vs vector<const A> vs const vector<const A> Javier C++ 2 09-04-2007 08:46 PM
Copy elements from one STL container to another STL container Marko.Cain.23@gmail.com C++ 4 02-16-2006 05:03 PM
About static const members appearing in another static const definitions Rakesh Sinha C++ 4 01-13-2005 08:11 AM



Advertisments