Prev: Help With TR1 regex_match()
Next: Is this correct C++?
From: ManicQin on 6 Oct 2009 13:14 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 6 Oct 2009 21:45 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 6 Oct 2009 21:47 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 6 Oct 2009 21:46 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 6 Oct 2009 21:46
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! ] |