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

vector <Base *> = vector <Derived *> ??

P: n/a
why is the following not allowed :

vector <Base *vec_of_base;
vector <Derived *vec_of_derived;
vec_of_base = vec_of_derived;

Note : The following is allowed :

Base *base_ptr;
Derived *derived_ptr;
base_ptr = derived_ptr;

How do things change when we use a vector ?

Jan 23 '07 #1
Share this Question
Share on Google+
16 Replies


P: n/a
call_me_anything wrote:
why is the following not allowed :

vector <Base *vec_of_base;
vector <Derived *vec_of_derived;
vec_of_base = vec_of_derived;

Because vector<Derived*is not derived from vector<Base*>. In fact,
considering the possibility of template specialization, vector<Derived*>
may be wildly different than vector<Base*>.
>
Note : The following is allowed :

Base *base_ptr;
Derived *derived_ptr;
base_ptr = derived_ptr;

How do things change when we use a vector ?
It's not unique to a vector. A relation between the template parameters
does not imply any relationship between the template classes.
Jan 23 '07 #2

P: n/a
"call_me_anything" <sg***@yahoo.comwrote in message
news:11*********************@q2g2000cwa.googlegrou ps.com...
why is the following not allowed :

vector <Base *vec_of_base;
vector <Derived *vec_of_derived;
vec_of_base = vec_of_derived;
It's hard to understand how one would implement such a feature without also
allowing

vector<Xvx;
vector<Yvy;

vx = vy;

whenever it is possible to convert Y to X. Such assignments could be
allowed in principle, but they can also be hazardous and inefficient. If
you want to achieve that effect, you can do so fairly easily:

vec_of_base.assign(vec_of_derived.begin(), vec_of_derived.end());

Please note that this question is completely different from the commonly
asked question about why it is not possible to convert a vector<Derived>* to
a vector<Base>*.
Jan 23 '07 #3

P: n/a

Andrew Koenig wrote:
"call_me_anything" <sg***@yahoo.comwrote in message
news:11*********************@q2g2000cwa.googlegrou ps.com...
why is the following not allowed :

vector <Base *vec_of_base;
vector <Derived *vec_of_derived;
vec_of_base = vec_of_derived;

It's hard to understand how one would implement such a feature without also
allowing

vector<Xvx;
vector<Yvy;

vx = vy;

whenever it is possible to convert Y to X.
You could use a combination of enable_if, is_pointer, and
is_base_of...maybe something like so:

template < typename other_val_type >
enable_if
<
mpl::and_
<
is_pointer<value_type>
, is_pointer<other_val_type>
, is_base_of<value_type, other_val_type>
>
, vector &
>
operator = ( vector<other_val_typeconst & right)
{
....??
}

Jan 23 '07 #4

P: n/a
On Jan 23, 8:31 pm, "call_me_anything" <s...@yahoo.comwrote:
why is the following not allowed :

vector <Base *vec_of_base;
vector <Derived *vec_of_derived;
vec_of_base = vec_of_derived;
...
How do things change when we use a vector ?
Well, and if we call these types not Base and Derived, having the
assignment base=derived being correct, will these vectors be equal,
without derivation relationships? We will have to do element-by-element
assignment anyway.

Although in this case there should work a trick, based on the equality
of Base* and Derived* entities -- they are pointers with same size. I'm
not quite sure whether it's correct, but i was once told to try
reinterpret_cast vec_of_base. Though, having been never tried out by
me, it seems reasonable.

Jan 24 '07 #5

P: n/a
call_me_anything wrote:
why is the following not allowed :

vector <Base *vec_of_base;
vector <Derived *vec_of_derived;
vec_of_base = vec_of_derived;

Note that the following is legal:

vector<Base *vec_of_base;
vector<Derived *vec_of_derived;
vec_of_base.assign(vec_of_derived.begin(), vec_of_derived.end());

Admittedly it's much wordier than your version, but it compiles and does
what you want.

Joe Gottman
Jan 24 '07 #6

P: n/a
why is the following not allowed :
>
vector <Base *vec_of_base;
vector <Derived *vec_of_derived;
vec_of_base = vec_of_derived;
I became curious enough to check it for myself.

vec_of_base=*reinterpret_cast<vector<Base*>*>(&vec _of_derived)

This does work, at least under MSVS.

Jan 24 '07 #7

P: n/a
"Pavel Shved" <Pa*********@gmail.comwrote in message
news:11**********************@m58g2000cwm.googlegr oups.com...
I became curious enough to check it for myself.
vec_of_base=*reinterpret_cast<vector<Base*>*>(&vec _of_derived)
This does work, at least under MSVS.
If it works, it does so only by coincidence.
Jan 24 '07 #8

P: n/a


On Jan 24, 8:54 am, "Andrew Koenig" <a...@acm.orgwrote:
vec_of_base=*reinterpret_cast<vector<Base*>*>(&vec _of_derived)
If it works, it does so only by coincidence.
Yes, coincidence is the exact reason why it does work. ;-) vector
<Base*and vector <Derived*are be byte-to-byte equal.

Jan 24 '07 #9

P: n/a


On Jan 23, 1:33 pm, "Noah Roberts" <roberts.n...@gmail.comwrote:
whenever it is possible to convert Y to X.You could use a combination of enable_if, is_pointer, and
is_base_of...maybe something like so:

template < typename other_val_type >
enable_if
<
mpl::and_
<
is_pointer<value_type>
, is_pointer<other_val_type>
, is_base_of<value_type, other_val_type>
>
, vector &
// HERE
operator = ( vector<other_val_typeconst & right)
{
...??

}
I don't normally respond to people that email me instead of posting to
the group but I decided in this case I would. Someone asked me two
questions:

1) Are these standard components or did I just make them up?

It is a combination of standard stuff and things that are found in
certain boost libraries. Some of it, including the is_pointer and
is_base_of traits, will be in the next standard. These are basic
metaprogramming techniques but if you've never seen metaprogramming it
might be rather difficult to understand.

2) Where does the last go?

Apparently google groups removed it. It should be on the line after
vector& and before "operator", I put it back.

Now, newsgroup etiquette says you post your replies to the group, not
the user. This is not only because it might be considered rude but so
that others can see the answer...now you know.

Jan 24 '07 #10

P: n/a
* Pavel Shved:
>
On Jan 24, 8:54 am, "Andrew Koenig" <a...@acm.orgwrote:
>>vec_of_base=*reinterpret_cast<vector<Base*>*>(&v ec_of_derived)
>If it works, it does so only by coincidence.

Yes, coincidence is the exact reason why it does work. ;-) vector
<Base*and vector <Derived*are be byte-to-byte equal.
Sorry, that's incorrect.

One might easily get the impression that these vectors would be
effectively equal because both are vectors of class type pointers, and
those pointer values are the same size, and so, unless the vector
implementation against all odds contains some unwarranted hacking, they
have the exact same /memory layout/.

But consider that reinterpret_cast<Base*>(pDerived) and
static_cast<Base*>(pDerived) do not always yield the same result.

So what you have is simply undefined behavior.

If it works, it works by coincidence, for a particular pair of Base and
Derived classes.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jan 24 '07 #11

P: n/a
"call_me_anything" <sg***@yahoo.comwrote:
why is the following not allowed :

vector <Base *vec_of_base;
vector <Derived *vec_of_derived;
vec_of_base = vec_of_derived;

Note : The following is allowed :

Base *base_ptr;
Derived *derived_ptr;
base_ptr = derived_ptr;

How do things change when we use a vector ?
Things change because the above doesn't work for arrays, thus it doesn't
work for vectors. As an example:

struct Base {
int x;
};

struct Derived : Base {
int y;
};

int main() {
Derived* derivedPtr = new Derived[2];
derivedPtr[0].y = 10;
Base* basePtr = derivedPtr;
basePtr[1].x = 0;
assert( derivedPtr[0].y == 10 );
delete [] derivedPtr;
}

The assert in the above will probably fail, even though it shouldn't.

The fact that the vector code fails to compile is yet another example of
why vectors are better than bald arrays.
Jan 24 '07 #12

P: n/a
"Pavel Shved" <Pa*********@gmail.comwrote in message
news:11*********************@l53g2000cwa.googlegro ups.com...
>If it works, it does so only by coincidence.
Yes, coincidence is the exact reason why it does work. ;-) vector
<Base*and vector <Derived*are be byte-to-byte equal.
You think so? How about trying it with these classes:

struct Base { };

struct Derived: virtual Base { };

Now the internal representations of a Derived* and a Base* pointing to the
same object are different.

As I said, if it works, it does so only by coincidence.
Jan 24 '07 #13

P: n/a
"Daniel T." <da******@earthlink.netwrote in message
news:da****************************@news.west.eart hlink.net...
"call_me_anything" <sg***@yahoo.comwrote:
>why is the following not allowed :

vector <Base *vec_of_base;
vector <Derived *vec_of_derived;
vec_of_base = vec_of_derived;

Note : The following is allowed :

Base *base_ptr;
Derived *derived_ptr;
base_ptr = derived_ptr;

How do things change when we use a vector ?

Things change because the above doesn't work for arrays, thus it doesn't
work for vectors. As an example:

struct Base {
int x;
};

struct Derived : Base {
int y;
};

int main() {
Derived* derivedPtr = new Derived[2];
derivedPtr[0].y = 10;
Base* basePtr = derivedPtr;
basePtr[1].x = 0;
assert( derivedPtr[0].y == 10 );
delete [] derivedPtr;
}

The assert in the above will probably fail, even though it shouldn't.

The fact that the vector code fails to compile is yet another example of
why vectors are better than bald arrays.
This argument would be better if the OP wanted to assign a vector<Derived>
to a vector<Base>. But he doesn't want that, he wants to assign a
vector<Derived*to a vector<Base*>. But aside from that, a vector
assignment will create a _copy_, so pointer magic has got nothing to do with
it - you can perfectly copy an array of Deriveds to an array of Base. You
can't use the assignment operator for it, but std::copy could cope with it
just fine. Of course, you're slicing the Deriveds, but hey, if that's what
you want you can get it ;).

Now, the reason why you can't assign a Derived** to a Base**, is because
then you could let a Derived* point to something other than a Derived
(similar with const).

Jan 24 '07 #14

P: n/a


On Jan 23, 11:00 pm, "Alf P. Steinbach" <a...@start.nowrote:
* Pavel Shved:
On Jan 24, 8:54 am, "Andrew Koenig" <a...@acm.orgwrote:
>vec_of_base=*reinterpret_cast<vector<Base*>*>(&ve c_of_derived)
If it works, it does so only by coincidence.
Yes, coincidence is the exact reason why it does work. ;-) vector
<Base*and vector <Derived*are be byte-to-byte equal.Sorry, that's incorrect.

One might easily get the impression that these vectors would be
effectively equal because both are vectors of class type pointers, and
those pointer values are the same size, and so, unless the vector
implementation against all odds contains some unwarranted hacking, they
have the exact same /memory layout/.

But consider that reinterpret_cast<Base*>(pDerived) and
static_cast<Base*>(pDerived) do not always yield the same result.
This is why I didn't fill out the body of my assignment op hack.

Is this code valid?

Derived * d = new Derived[20]();
Base * b = static_cast<Base*>(d);

b[10]->f();

delete [] b;

For all possible constructions of Base and Derived? (assuming a
parental is-a relation)

I believe it should be, but in all honesty I've never had to do
anything remotely like this.

Jan 24 '07 #15

P: n/a
"Noah Roberts" <ro**********@gmail.comwrote in message
news:11**********************@v45g2000cwv.googlegr oups.com...
Is this code valid?

Derived * d = new Derived[20]();
Base * b = static_cast<Base*>(d);

b[10]->f();

delete [] b;

For all possible constructions of Base and Derived? (assuming a
parental is-a relation)
No way.

It will usually work in practice provided that Base has a virtual destructor
and sizeof(Base) == sizeof(Derived), but not otherwise. Moreover, it's not
guaranteed to work in any circumstances.
Jan 24 '07 #16

P: n/a


On Jan 24, 11:23 am, "Andrew Koenig" <a...@acm.orgwrote:
"Noah Roberts" <roberts.n...@gmail.comwrote in messagenews:11**********************@v45g2000cwv.g ooglegroups.com...
Is this code valid?
Derived * d = new Derived[20]();
Base * b = static_cast<Base*>(d);
b[10]->f();
delete [] b;
For all possible constructions of Base and Derived? (assuming a
parental is-a relation)No way.

It will usually work in practice provided that Base has a virtual destructor
and sizeof(Base) == sizeof(Derived), but not otherwise. Moreover, it's not
guaranteed to work in any circumstances.
Yeah, nm. I knew that. Wasn't thinking clearly. Meant something more
along the lines of Base ** ptr = static_cast<Base**>(dptr), which is
not valid at any rate. If there was a way for the vector to swap it's
buffer pointer with the other vector there might be a benifit to op=
for base/derived vectors but I don't see that as being reliably
possible.

Jan 24 '07 #17

This discussion thread is closed

Replies have been disabled for this discussion.