For Programmers: Free Programming Magazines  


Home > Archive > VC STL > April 2005 > downcast copy algorithm request









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author downcast copy algorithm request
Christopher Yeleighton

2005-04-26, 4:04 pm

// Consider the following piece of code:

#include<algorithm>

class A { int a; };
class B: public A { int b; };

void f(void) {
B b;
A *pa[01];
B *pb[01];
std::fill(pa, pa + 01, &b); // :-)
std::copy(pa, pa + 01, pb); // x(: assignment requires cast
}

// An algorithm for such a situation is needed.

Igor Tandetnik

2005-04-26, 4:04 pm

"Christopher Yeleighton"
<ChristopherYeleighton@discussions.microsoft.com> wrote in message
news:2747BD14-7F75-48A8-A5FD-B4D06E29DB51@microsoft.com
> // Consider the following piece of code:
>
> #include<algorithm>
>
> class A { int a; };
> class B: public A { int b; };
>
> void f(void) {
> B b;
> A *pa[01];
> B *pb[01];
> std::fill(pa, pa + 01, &b); // :-)


This won't compile. You probably mean

std::fill(pa, pa + 01, b); // no ampersand

> std::copy(pa, pa + 01, pb); // x(: assignment requires cast


What did you expect? You are copying from an array of A's into an array
of B's, but you have not provided any way to construct a B given an A. A
cast won't help you here.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925


Christopher Yeleighton

2005-04-26, 8:59 pm



„Igor Tandetnik” pisze:

[color=darkred]
> What did you expect? You are copying from an array of A's into an array
> of B's, but you have not provided any way to construct a B given an A. A


Come on. Where did you see an array of class A?
Doug Harrison [MVP]

2005-04-26, 8:59 pm

On Tue, 26 Apr 2005 10:48:03 -0700, Christopher Yeleighton wrote:

> // Consider the following piece of code:
>
> #include<algorithm>
>
> class A { int a; };
> class B: public A { int b; };
>
> void f(void) {
> B b;
> A *pa[01];


Don't write 0 in front of constants like this. It creates an octal literal
and falls apart when it comes to 8 and 9.

> B *pb[01];
> std::fill(pa, pa + 01, &b); // :-)
> std::copy(pa, pa + 01, pb); // x(: assignment requires cast
> }


You need to adapt the input iterator to return a B* using static_cast or
dynamic_cast, whichever is appropriate. I think you can use Boost
transform_iterator for this or the lambda library:

http://www.boost.org/libs/iterator/...m_iterator.html
http://www.boost.org/doc/html/lambda.html

Or, you can write your own minimalistic input iterator adapter class, which
you would use something like this:

std::copy(
static_cast_iterator<B*>(pa),
static_cast_iterator<B*>(pa+1),
pb);

Or, you could simply write the loop out by hand. :)

--
Doug Harrison
Microsoft MVP - Visual C++
Igor Tandetnik

2005-04-26, 8:59 pm

"Christopher Yeleighton"
<ChristopherYeleighton@discussions.microsoft.com> wrote in message
news:267F4759-D455-4B57-A311-29DF519527F0@microsoft.com
> "Igor Tandetnik" pisze:
>
>
>
> Come on. Where did you see an array of class A?


Oops, sorry. Now I see what you are trying to do.

You can do std::transform with a suitable predicate. If you insist on
using copy, you can try an iterator adaptor, like
boost::transform_iterator

http://boost.org/libs/iterator/doc/...m_iterator.html

--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925


Christopher Yeleighton

2005-04-26, 8:59 pm



"Doug Harrison [MVP]" wrote:

> Or, you can write your own minimalistic input iterator adapter class, which
> you would use something like this:
>
> std::copy(
> static_cast_iterator<B*>(pa),
> static_cast_iterator<B*>(pa+1),
> pb);
>


I tried but I stumped over the following problem. I present it in an
isolated form.

template<class wrapped_t>

struct wrapper {

wrapped_t x;

wrapper(wrapped_t c): x(c) {

}

wrapper &operator =(wrapped_t c) {

x = c;

return *this;

}

operator wrapped_t &(void) {

return x;

}

operator wrapped_t const &(void) const {

return x;

}

};



inline void test_wrapper(void) {

wrapper<int> x(00);

wrapper<int *> y(00);

++x;

++y; // error C2675: unary '++' : 'wrapper<wrapped_t>' does not define this
operator or a conversion to a type acceptable to the predefined operator

}





Comeau compiles it without an error but MSVC prohibits me from incrementing
the pointer whereas it allows me to increment the integer. It does not make
sense.


Christopher Yeleighton

2005-04-26, 8:59 pm



"Igor Tandetnik" wrote:

> You can do std::transform with a suitable predicate. If you insist on


Thanks. Here is my solution for the predicate:

template<class T1, class T2> inline T1 do_static_cast(T2 x) {
return static_cast<T1>(x);
}
template<class T1, class T2> inline T1 (&make_static_cast(T1, T2))(T2) {
return do_static_cast<T1, T2>;
}

I still wonder why such solutions are not included in <functional>. The
selection of operator wrappers is somewhat arbitrary.

Doug Harrison [MVP]

2005-04-26, 8:59 pm

On Tue, 26 Apr 2005 13:10:14 -0700, Christopher Yeleighton wrote:

> "Doug Harrison [MVP]" wrote:
>
>
> I tried but I stumped over the following problem. I present it in an
> isolated form.
>
> template<class wrapped_t>
>
> struct wrapper {
>
> wrapped_t x;
>
> wrapper(wrapped_t c): x(c) {
>
> }
>
> wrapper &operator =(wrapped_t c) {
>
> x = c;
>
> return *this;
>
> }
>
> operator wrapped_t &(void) {
>
> return x;
>
> }
>
> operator wrapped_t const &(void) const {
>
> return x;
>
> }
>
> };
>
>
>
> inline void test_wrapper(void) {
>
> wrapper<int> x(00);
>
> wrapper<int *> y(00);
>
> ++x;
>
> ++y; // error C2675: unary '++' : 'wrapper<wrapped_t>' does not define this
> operator or a conversion to a type acceptable to the predefined operator
>
> }
>
> Comeau compiles it without an error but MSVC prohibits me from incrementing
> the pointer whereas it allows me to increment the integer. It does not make
> sense.


That's not the right approach. You'll need to define operator->, operator*,
operator++, operator==, etc instead of trying to make do with a reference
conversion operator. You also have to provide a few standard typedefs. You
can find some examples in your STL implementation, by searching the web,
looking at the Boost link I gave last time, etc.

That said, I see Igor directed you to transform, which I tend not to think
of when I want to copy something. :|

--
Doug Harrison
Microsoft MVP - Visual C++
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com