|
From: Mathias Gaunard on 6 May 2008 09:43 On 6 mai, 20:46, Krzysztof Czainski <1czaj...(a)gmail.com> wrote: > I don't understand where do I require default-constructible? My bad, I had incorrectly read. > Can You perhaps > see a way to avoid usage of new? struct Cloneable { virtual std::size_t sizeof_() const = 0; // returns size of object virtual void clone(void* p) const = 0; // performs placement-new on p, copying the object }; then, for example const A& a = B(); A* copy; try { copy = static_cast<A*>(::operator new(a.sizeof_())); a.clone(copy); } catch(...) { ::operator delete(copy); throw; } That way the user can choose how to allocate the memory. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Daniel Krügler on 6 May 2008 09:43 On 5 Mai, 15:10, Krzysiek Czain'ski "Czajnik" <1czaj...(a)gmail.com> wrote: > I'm working on a Cloneable concept for C++ classes. Here's what I > think it should be like, however it doesn't compile :? > > #include <memory> > > class CloneableBase > { > public: > virtual ~CloneableBase() {} > private: > virtual CloneableBase* doClone() const = 0; > > }; > > template < typename Derived > > class Cloneable : public CloneableBase > { > public: > typedef std::auto_ptr<Derived> AutoPtr; > AutoPtr clone() const { return AutoPtr( doClone() ); } > private: > virtual Derived* doClone() const = 0; // COMPILE ERROR > > }; > > class A : public Cloneable<A> > { > virtual A* doClone() { return new A( *this ); } Probably you meant a const version of this: virtual A* doClone() const { return new A( *this ); } > > }; > > int main() > { > { > A a; > A::AutoPtr pa = a.clone(); > } > > } > > cloneable.cpp:17: error: invalid covariant return type for 'Derived* > Cloneable<Derived>::doClone() const [with Derived = A]' > gcc version 4.2.3 (Gentoo 4.2.3 p1.0) > > MSVC.NET 2005 gives a similar error on this.. > > The C++ standard says (10.3.5) > The return type of an overriding function shall be either identical to > the return type of the > overridden function or covariant with the classes of the functions. > > Since Derived = A, it is derived from CloneableBase, through > Cloneable<A>, so Derived is covariant with CloneableBase. > > Is my understanding wrong, or is this the compilers' bug, or maybe > it's just the way it is supposed to be, and I misunderstand the C++ > standard? I'm also looking forward to comments on design/style. First, the compilers are all correct to reject your code, as others have already mentioned. The reason is that you omitted to mention this part from p. 5: "If the return type of D::f differs from the return type of B::f, the class type in the return type of D::f shall be complete at the point of declaration of D::f or shall be the class type D." In your example, Derived is incomplete at this point and different from Cloneable. Your problem is an interesting one and has been issued several times (longer than a decade) in this an related newsgroups. IMO the next matching solution given your ansatz is the following one. It deviates only slightly from your original approach in that it makes the CloneableBase::doClone() protected instead of private - I don't think that this causes much harm. The class template uses a static_cast, but this should be safe, because it still is an abstract class (implicitly) and if the provided template parameter does not correspond to a derived class, it should not compile.[1] #include <memory> class CloneableBase { public: virtual ~CloneableBase() {} protected: virtual CloneableBase* doClone() const = 0; }; template < typename Derived> class Cloneable : public CloneableBase { public: typedef std::auto_ptr<Derived> AutoPtr; AutoPtr clone() const { return AutoPtr( static_cast<Derived*>(this->doClone()) ); } }; class A : public Cloneable<A> { virtual A* doClone() const { return new A( *this ); } }; int main() { { A a; A::AutoPtr pa = a.clone(); } } HTH & Greetings from Bremen, Daniel Kr�gler [1] If you really want, you can outsmart the mechanism like this, but I'm not talking about Machiavelli: class B : public Cloneable<A> { virtual A* doClone() const { return new A(); } }; -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
|
Pages: 1 Prev: Exceptions vs. undefined behaviour Next: Calling shared_from_this inside object's constructor |