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++
|
|
|
|
|