From: ManicQin on
Hi, I'll do my best to explain my problem...
I have an data type that is wrapping a vector of pointers, currently I
have no control of the type that the vector holds and I need to be as
generic as I can (it's a part of a frame work).
naturally my vector is templated by the client.

I tried to think of a way to deep copy the vector into another -
>without<- adding Clone function and such to the objects and I couldnt
think of one, I would be happy if anyone knows of a way...

Because I couldnt find a way to work without the Clone() AND I cant
force my clients to implement IClonable interface than I decided to
check If the object is descendant of IClonable and if it is than I
deep copy the object if not than I shallow copy the object, it seems
something like this:

void CompositorBase<Interface>::CopyItems(CompositorBase<Interface>
const& compositor)
{
for(CIterator iter = compositor.m_cData.begin();
iter != compositor.m_cData.end();
iter++)
{
Interface* newItem = (*iter);
IClonable* testForClonable = dynamic_cast<IClonable*>(newItem);
if (testForClonable)
{
IClonable* tmpClone = testForClonable->Clone();
if (tmpClone)
{
newItem = dynamic_cast<Interface*>(tmpClone);
}
}

this->AddItem(newItem);
}
}

Now... I dont like this chunk of code, Can any one think of better way
under this restrictions?

thank you!

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Nick Hounsome on
On 7 Oct, 05:14, ManicQin <manic...(a)gmail.com> wrote:
> Hi, I'll do my best to explain my problem...
> I have an data type that is wrapping a vector of pointers, currently I
> have no control of the type that the vector holds and I need to be as
> generic as I can (it's a part of a frame work).
> naturally my vector is templated by the client.
>
> I tried to think of a way to deep copy the vector into another ->without<-
adding Clone function and such to the objects and I couldnt
>
> think of one, I would be happy if anyone knows of a way...
>
> Because I couldnt find a way to work without the Clone() AND I cant
> force my clients to implement IClonable interface than I decided to
> check If the object is descendant of IClonable and if it is than I
> deep copy the object if not than I shallow copy the object, it seems
> something like this:
>
> void CompositorBase<Interface>::CopyItems(CompositorBase<Interface>
> const& compositor)
> {
> for(CIterator iter = compositor.m_cData.begin();
> iter != compositor.m_cData.end();
> iter++)
> {
> Interface* newItem = (*iter);
> IClonable* testForClonable =
dynamic_cast<IClonable*>(newItem);
> if (testForClonable)
> {
> IClonable* tmpClone =
testForClonable->Clone();
> if (tmpClone)
> {
> newItem =
dynamic_cast<Interface*>(tmpClone);
> }
> }
>
> this->AddItem(newItem);
> }
> }
>
> Now... I dont like this chunk of code, Can any one think of better way
> under this restrictions?
>
> thank you!

I think that it is fundamentally wrong to have the behaviour of a
method depend on runtime typing in this way.
It is impossible to document well - "This method does a deep copy
except when it doesn't - and it may be deep in some places and not
others".
Finding bugs will be extremely difficult and you will be the one who
is blamed.

You should either abandon the method entirely since it cannot have a
reasonable function in general or, if you insist, have a partial
specialisation for ICloneable (This probably wont fit in with your
current framework but that would indicate to me that your framework is
flawed).

In my experience developing a framework that isn't strongly grounded
in real application requirements often leads to this sort of mess
where the developer struggles to create something that could do
everything but actually just constrains the users (I'm trying not to
sound too judgemental - I've been guilty myself). From my user point
of view you are making me derive all my classes from your interfaces
just to get some functionality that is harder to maintain than just
using an STL or boost container (and the fact that there is no copy in
the boost pointer containers should tell you something).


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: CornedBee on
On Oct 7, 6:14 am, ManicQin <manic...(a)gmail.com> wrote:
> Hi, I'll do my best to explain my problem...
> I have an data type that is wrapping a vector of pointers, currently I
> have no control of the type that the vector holds and I need to be as
> generic as I can (it's a part of a frame work).
> naturally my vector is templated by the client.
>
> I tried to think of a way to deep copy the vector into another ->without<-
adding Clone function and such to the objects and I couldnt
> think of one, I would be happy if anyone knows of a way...

If you want to deep-copy a pointer to something polymorphic, you need
a Clone function. There is no way around this.

Sebastian


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Ulrich Eckhardt on
ManicQin wrote:
> I have an data type that is wrapping a vector of pointers, currently I
> have no control of the type that the vector holds and I need to be as
> generic as I can (it's a part of a frame work).
> naturally my vector is templated by the client.
>
> I tried to think of a way to deep copy the vector into another
> ->without<- adding Clone function and such to the objects and I couldnt
> think of one, I would be happy if anyone knows of a way...
>
> Because I couldnt find a way to work without the Clone() AND I cant
> force my clients to implement IClonable interface than I decided to
> check If the object is descendant of IClonable and if it is than I
> deep copy the object if not than I shallow copy the object

So, what are the guarantees of that operation? You claim that you make a
deep copy of the vector into another, but if you find you can't you fall
back to a shallow copy? I'd say that this is useless, exactly because it
doesn't give any guarantee at all about the results. You simply don't know
if the new vector owns the contained objects or just shares them, so you
also don't know if you can delete the objects, who owns them etc. Note that
a reference-counted smart pointer would help to at least make this safe
from the C++ side, though I still question if a half-deep copy fits the
application logic.

> Interface* newItem = (*iter);
> IClonable* testForClonable = dynamic_cast<IClonable*>(newItem);
> if (testForClonable)
> {
> IClonable* tmpClone = testForClonable->Clone();
> if (tmpClone)
> {
> newItem = dynamic_cast<Interface*>(tmpClone);
> }
> }
>
> this->AddItem(newItem);

Actually, I'd do it differently:
1. If the type (not the object, i.e. don't check that on every iteration)
supports cloning, use the clone function.
2. If the type doesn't support cloning, it still has a copy-constructor.
However, in order to avoid slicing, make sure that
typeid(*original_ptr)==typeid(*clone_ptr)
still holds.

Note that case 2 will lead to compile-time errors if you can't access the
copy constructor (as is the case with many baseclasses) and at least yield
runtime errors if the type is just a baseclass and the object's type is
some unknown derived type.

However, and that is the important part, you either end up with a deep copy
or you will get an error.

Uli

--
Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Neil Butterworth on
ManicQin wrote:
> Hi, I'll do my best to explain my problem...
> I have an data type that is wrapping a vector of pointers, currently I
> have no control of the type that the vector holds and I need to be as
> generic as I can (it's a part of a frame work).
> naturally my vector is templated by the client.
>
> I tried to think of a way to deep copy the vector into another -
>> without<- adding Clone function and such to the objects and I couldnt
> think of one, I would be happy if anyone knows of a way...

Presumably your class looks like this:

template <typename T>
class C {
public:
// stuff
private:
std::vector <T*> v;
};

in which case why not add a copy constructor that "deep copies" by using
the copy constructor of the things pointed to by the vector:

C( const C & c ) {
for( int i = 0; i < c.v.size(); i++ ) {
v.push_back( new T( *c.v.at(i) ));
}
}

This of course does not give you polymorphic copying - if you want that,
I think forcing your clients to supply a virtual Clone() function is the
most sensible solution.

Neil Butterworth



--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

 |  Next  |  Last
Pages: 1 2 3
Prev: Help With TR1 regex_match()
Next: Is this correct C++?