Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Deep Copy smart pointer not requiring virtual copy constructor

Reply
Thread Tools

Deep Copy smart pointer not requiring virtual copy constructor

 
 
Nindi73@yahoo.co.uk
Guest
Posts: n/a
 
      11-12-2006
A few days a ago I posted my code for a deep copy pointer which
doesn't require the pointee object to have a virtual copy constructor.
I need help with checking that it was exception safe and exception
neutral/
I got a reply from Bux with his code for a smart pointer with far fewer
lines of code
and more cleaner design, not over engineered like mine.

http://groups.google.co.uk/group/com...e5c18bc6bb5c7e


However there was one possible extension to that code :

'The trade-off is that copy_ptr<Base> and copy_ptr<Derived> are
unrelated '
Kai-Uwe Bux
I think I have managed to implement this extension, so I post my code
here along with a main.cpp that exhibists the extension.

Any comments about my abuse of the language would be more than welcome
--------------------------------------------------------------------------------------------------------------
<smart_ptr_policies.h>
#ifndef SMART_POINTER_POLICIES_HEADER
#define SMART_POINTER_POLICIES_HEADER


#include<algorithm>
#include<boost/utility.hpp>
#include<boost/type_traits.hpp>

//
http://groups.google.co.uk/group/com...hread/thread/b...



template<class DerivedClass>
void * Buxclone(const void *theOtherPtr){
return new DerivedClass(*static_cast<const
DerivedClass*>(theOtherPtr));
}


template<class BaseClass>
struct BuxWrappedPointer {

template<class T>
friend struct BuxWrappedPointer;

BuxWrappedPointer():raw_pointer(0),theCloner(0){}

template<class DerivedClass>
BuxWrappedPointer(DerivedClass * ptr):raw_pointer(ptr),
theCloner(&Buxclone<DerivedClass>){}


BuxWrappedPointer(const BuxWrappedPointer &theOther):
theCloner(theOther.theCloner),
raw_pointer(theOther.clone(theOther.raw_pointer)){ }

template<class MiddleBase>
BuxWrappedPointer(const BuxWrappedPointer<MiddleBase>
&theMiddleBase,
typename
boost::enable_if<boost::is_base_of<BaseClass,Middl eBase>,MiddleBase>::type
*pp=0):
theCloner(theMiddleBase.theCloner),
raw_pointer(static_cast<BaseClass *>
(theMiddleBase.theCloner(static_cast<const BaseClass
*>(theMiddleBase.raw_pointer)))){}

BuxWrappedPointer<BaseClass> & operator=(const
BuxWrappedPointer<BaseClass> &theOther)
{
BuxWrappedPointer<BaseClass> temp(theOther);
std::swap(temp.raw_pointer,raw_pointer);
return *this;
}


BaseClass * raw_pointer;


~BuxWrappedPointer(){delete raw_pointer;}
private:
BaseClass *clone(const BaseClass * theSource)const{
return static_cast<BaseClass*>(theCloner(static_cast<cons t
BaseClass*>(theSource)));
}
typedef void * (*clone_)(const void *);
clone_ theCloner;


};
#endif
--------------------------------------------------------------------------------------------------------------
<smart_ptr.h>

#ifndef SMART_POINTER__HEADER
#define SMART_POINTER__HEADER

#include"smart_ptr_policies.h"

template<
class BaseClass,
template <class> class CLONE_POLICY
>

class smart_ptr {
public:
typedef typename boost::remove_const<BaseClass>::type non_const_base;

template<class T,template <class> class CLONE_POLICY >
friend class smart_ptr;

template<class DerivedClass>
smart_ptr(DerivedClass *
theDerivedPointer_):theWrappedPointer(theDerivedPo inter_){}

smart_ptr(const smart_ptr<non_const_base,CLONE_POLICY>&
theOtherSmart_ptr):
theWrappedPointer(theOtherSmart_ptr.theWrappedPoin ter){}

smart_ptr(const smart_ptr<const non_const_base,CLONE_POLICY>&
theOtherSmart_ptr):
theWrappedPointer(theOtherSmart_ptr.theWrappedPoin ter){}

template<class T>
smart_ptr(const smart_ptr<T,CLONE_POLICY>& theOtherSmart_ptr,
typename boost::enable_if<boost::is_base_of<non_const_base, typename
boost::remove_const<T>::type>,T>::type *pp=0):
theWrappedPointer(theOtherSmart_ptr.theWrappedPoin ter){}

smart_ptr(){}

BaseClass *operator->()const{return
theWrappedPointer.raw_pointer;}

virtual ~smart_ptr(){}


private:
smart_ptr & operator=(const BaseClass *ptr);

CLONE_POLICY<non_const_base> theWrappedPointer;


};


#endif
--------------------------------------------------------------------------------------------------------------
<main.cpp>
#include<vector>
#include<iostream>

#include<cctype>
#include"smart_ptr.h"

using namespace std;


class Base {
public:
Base():ch('*'){
Count++;
}
Base(const Base&):ch('*'){
Count++;
}
virtual char show(){
return ch;
}
virtual ~Base(){Count--;}
virtual void v()const=0;
static unsigned long Count;
private:
char ch;
};
unsigned long Base::Count(0);

/// this will give us lots of derived classes
template<char ch_>
class Derived ublic Base {
public:
Derived():ch(ch_){
Count++;
}
Derived(const Derived<ch_>&):ch(ch_){
Count++;
}
virtual char show(){
return ch;
}
virtual ~Derived(){Count--;}
virtual void v()const{}
static unsigned long Count;
private:
char ch;

};
template<char ch_>
unsigned long Derived<ch_>::Count(0);

template<char ch_>
class DerivedSquared ublic Derived<ch_> {
public:
DerivedSquared():ch(std::tolower(ch_)){
Count++;
}
DerivedSquared(const DerivedSquared<ch_>&):ch(std::tolower(ch_)){
Count++;
}
virtual char show(){return ch;}
virtual ~DerivedSquared(){Count--;}
virtual void v()const{}
static unsigned long Count;
private:
char ch;

};
template<char ch_>
unsigned long DerivedSquared<ch_>::Count(0);




int main() {

smart_ptr<Derived<'B'>,BuxWrappedPointer> theDPA(new
DerivedSquared<'B'>);
cout << theDPA->show();

smart_ptr<Base,BuxWrappedPointer> theDPA2(theDPA);
cout << theDPA2->show();


}


-------------------------------------------------------------------------------------------------------------------------
NSC

 
Reply With Quote
 
 
 
 
Gianni Mariani
Guest
Posts: n/a
 
      11-12-2006
http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:
> A few days a ago I posted my code for a deep copy pointer which
> doesn't require the pointee object to have a virtual copy constructor.
> I need help with checking that it was exception safe and exception
> neutral/
> I got a reply from Bux with his code for a smart pointer with far fewer
> lines of code
> and more cleaner design, not over engineered like mine.
>
> http://groups.google.co.uk/group/com...e5c18bc6bb5c7e
>
>
> However there was one possible extension to that code :
>
> 'The trade-off is that copy_ptr<Base> and copy_ptr<Derived> are
> unrelated '
> Kai-Uwe Bux
> I think I have managed to implement this extension, so I post my code
> here along with a main.cpp that exhibists the extension.


Why do you need such a beast ? i.e. what are the requirements and use case ?

>
> Any comments about my abuse of the language would be more than welcome


It's kind of hard to read.
 
Reply With Quote
 
 
 
 
Kai-Uwe Bux
Guest
Posts: n/a
 
      11-12-2006
(E-Mail Removed) wrote:
> A few days a ago I posted my code for a deep copy pointer which
> doesn't require the pointee object to have a virtual copy constructor.
> I need help with checking that it was exception safe and exception
> neutral/
> I got a reply from Bux with his code for a smart pointer with far fewer
> lines of code
> and more cleaner design, not over engineered like mine.
>
>

http://groups.google.co.uk/group/com...e5c18bc6bb5c7e
>
>
> However there was one possible extension to that code :
>
> ********'The trade-off is that *copy_ptr<Base> and copy_ptr<Derived> are
> unrelated '
> Kai-Uwe Bux
> I think I have managed to implement this extension, so I post my code
> here along with a main.cpp that exhibists the extension.


What a coincidence, your post prompted me to rethink that, too. I appears
that we arrived at very similar conclusions (see below).


> Any comments about my abuse of the language would be more than welcome


General comment: you lines are too long.


> --------------------------------------------------------------------------------------------------------------
> <smart_ptr_policies.h>
> #ifndef SMART_POINTER_POLICIES_HEADER
> #define SMART_POINTER_POLICIES_HEADER
>
>
> #include<algorithm>
> #include<boost/utility.hpp>
> #include<boost/type_traits.hpp>
>
> //
> http://groups.google.co.uk/group/com...hread/thread/b...
>
>
>
> template<class DerivedClass>
> void * Buxclone(const void *theOtherPtr){
> * * * * * * * * return new DerivedClass(*static_cast<const
> DerivedClass*>(theOtherPtr));
> }
>
>
> template<class BaseClass>
> struct BuxWrappedPointer {
>
> ******** * template<class T>
> ******** * friend *struct BuxWrappedPointer;
>
> * * * *BuxWrappedPointer():raw_pointer(0),theCloner(0){}
>
> * * * *template<class DerivedClass>
> * * * * * * *BuxWrappedPointer(DerivedClass * ptr):raw_pointer(ptr),
> ******************************** theCloner(&Buxclone<DerivedClass>){}
>
>
> * * * *BuxWrappedPointer(const BuxWrappedPointer &theOther):
> ************************ theCloner(theOther.theCloner),
> ********************************
> ********************************raw_pointer(theOther.clone(theOther.raw_pointer))
> ********************************{}
>
> ******** * template<class MiddleBase>
> ******** * BuxWrappedPointer(const BuxWrappedPointer<MiddleBase>
> &theMiddleBase,
> ********************************typename
> boost::enable_if<boost::is_base_of<BaseClass,Middl eBase>,MiddleBase>::type
> *pp=0):
> ****************************************theCloner(theMiddleBase.theCloner),
> ****************************************raw_pointer(static_cast<BaseClass

*>
> ************************************************(theMiddleBase.theCloner(static_cast<const

BaseClass
> *>(theMiddleBase.raw_pointer)))){}
>
> * * * *BuxWrappedPointer<BaseClass> & operator=(const
> BuxWrappedPointer<BaseClass> &theOther)
> ******** * {
> **************** * BuxWrappedPointer<BaseClass> temp(theOther);
> * * * * * *std::swap(temp.raw_pointer,raw_pointer);
> * * * * * *return *this;
> ******** * }
>
>
> * * * BaseClass * raw_pointer;
>
>
> * * *~BuxWrappedPointer(){delete raw_pointer;}
> private:
> ******** *BaseClass *clone(const BaseClass * theSource)const{
> ****************return static_cast<BaseClass*>(theCloner(static_cast<cons t
> BaseClass*>(theSource)));
> ******** *}
> * * * typedef void * (*clone_)(const void *);
> * * * clone_ *theCloner;
>
>
> };
> #endif
> --------------------------------------------------------------------------------------------------------------


Oh boy, you are quite boost-savvy! I do not quite see, however, what all
this enable_if< ... > stuff is doing for you. If it is just to get the
right compiler errors if you do

copy_ptr< Base > b_ptr = copy_ptr< NotDerived >( new not Derived() );

then, I think, there are simpler means of going about it (see below). But I
might be missing something here.

> <smart_ptr.h>
>
> #ifndef SMART_POINTER__HEADER
> #define SMART_POINTER__HEADER
>
> #include"smart_ptr_policies.h"
>
> template<
> * * * * class BaseClass,
> * * * * template <class> class CLONE_POLICY
> >

> class smart_ptr {
> public:
> ****************typedef typename boost::remove_const<BaseClass>::type
> ****************non_const_base;
>
> ****************template<class T,template <class> class CLONE_POLICY >
> ****************friend class smart_ptr;


g++ gives me an error for the above saying that the declaration of
CLONE_POLICY shadows the template parameter.

>
> * * * * template<class DerivedClass>
> * * * * * * *smart_ptr(DerivedClass *
> theDerivedPointer_):theWrappedPointer(theDerivedPo inter_){}
>
> ****************smart_ptr(const smart_ptr<non_const_base,CLONE_POLICY>&
> theOtherSmart_ptr):
> ************************
> ************************theWrappedPointer(theOtherSmart_ptr.theWrappedPoin ter)
> ************************{}
>
> ****************smart_ptr(const smart_ptr<const
> ****************non_const_base,CLONE_POLICY>&
> theOtherSmart_ptr): ************************
> ************************theWrappedPointer(theOtherSmart_ptr.theWrappedPoin ter)
> ************************{}
>
> ****************template<class T>
> ************************smart_ptr(const smart_ptr<T,CLONE_POLICY>&
> ************************theOtherSmart_ptr,
> ********************************typename
> ********************************boost::enable_if<boost::is_base_of<non_const_base, typename
> boost::remove_const<T>::type>,T>::type
> *pp=0):
> ****************************************theWrappedPointer(theOtherSmart_ptr.theWrappedPoin ter)
> ****************************************{}
>
> * * * * smart_ptr(){}
>
> * * * * BaseClass *operator->()const{return
> theWrappedPointer.raw_pointer;}
>
> ****************virtual ~smart_ptr(){}


Why is this destructor virtual?

>
>
> private:
> * * * * smart_ptr & operator=(const BaseClass *ptr);
>
> * * * * CLONE_POLICY<non_const_base> theWrappedPointer;
>
>
> };
>
>
> #endif


Again, I find the boost stuff confusing. What design specs necessitate the
use of non_const_base and remove_const?

> <main.cpp>
> #include<vector>
> #include<iostream>
>
> #include<cctype>
> #include"smart_ptr.h"
>
> using namespace std;
>
>
> class Base {
> public:
> ********Base():ch('*'){
> ****************Count++;
> ********}
> ********Base(const Base&):ch('*'){
> ****************Count++;
> ********}
> ********virtual char show(){
> ****************return ch;
> ********}
> ********virtual ~Base(){Count--;}
> ********virtual void v()const=0;
> ********static unsigned long Count;
> private:
> ********char ch;
> };
> unsigned long Base::Count(0);
>
> /// this will give us lots of derived classes
> template<char ch_>
> class Derived ublic Base {
> public:
> ********Derived():ch(ch_){
> ****************Count++;
> ********}
> ********Derived(const Derived<ch_>&):ch(ch_){
> ****************Count++;
> ********}
> ********virtual char show(){
> ****************return ch;
> ********}
> ********virtual ~Derived(){Count--;}
> ********virtual void v()const{}
> ********static unsigned long Count;
> private:
> ********char ch;
>
> };
> template<char ch_>
> unsigned long Derived<ch_>::Count(0);
>
> template<char ch_>
> class DerivedSquared ublic Derived<ch_> {
> public:
> ********DerivedSquared():ch(std::tolower(ch_)){
> ****************Count++;
> ********}
> ********DerivedSquared(const DerivedSquared<ch_>&):ch(std::tolower(ch_)){
> ****************Count++;
> ********}
> ********virtual char show(){return ch;}
> ********virtual ~DerivedSquared(){Count--;}
> ********virtual void v()const{}
> ********static unsigned long Count;
> private:
> ********char ch;
>
> };
> template<char ch_>
> unsigned long DerivedSquared<ch_>::Count(0);
>
>
>
>
> int main() {
>
> ********smart_ptr<Derived<'B'>,BuxWrappedPointer> theDPA(new
> DerivedSquared<'B'>);
> ********cout << theDPA->show();
>
> ********smart_ptr<Base,BuxWrappedPointer> theDPA2(theDPA);
> ********cout << theDPA2->show();
>
>
> }


I found that

smart_ptr<int> i_ptr ( new int ( 5 ) );
cout << *i_ptr << '\n';

gives me an error. You should add operator*.



I worked a little on the non-policy based version to have copy_ptr<Base> and
copy_ptr<Derived> behave as desired. I also added a compile time check
agains using non-polymorphic base classes. This might be overkill.
(Alternatively, one could think about adding a deleter-function that would
use the right destructor in any case.)


#include <algorithm> // std::swap

template < typename T >
struct non_polymorphic_class_error {
enum {
trigger = sizeof( dynamic_cast<void*>( static_cast<T*>(0) ) )
};

};


// The clone function:
// ===================
template < typename T >
void * clone ( void * ptr ) {
return ( ptr == 0 ? 0
: static_cast<void*>
( new T ( *( static_cast<T*>( ptr ) ) ) ) );
}

// The copy_ptr:
// =============

template < typename T >
class copy_ptr {

friend void swap ( copy_ptr<T> & p, copy_ptr<T> & q ) {
std::swap( p.raw_ptr, q.raw_ptr );
std::swap( p.clone_fct, q.clone_fct );
}

template < typename D >
friend class copy_ptr;

/*
The idea is that in addition to a pointer, we also need
a pointer to the _appropriate_ clone function.
*/
T * raw_ptr;
void * ( *clone_fct ) ( void * );

public:

copy_ptr ( T * ptr = 0)
: raw_ptr ( ptr )
, clone_fct ( clone<T> )
{}

template < typename D >
copy_ptr ( D * ptr )
: raw_ptr ( ptr )
, clone_fct ( clone<D> )
{
non_polymorphic_class_error<T> d2;
}

// copy construction clones:
copy_ptr ( copy_ptr const & other )
: raw_ptr ( static_cast<T*>( other.clone_fct( other.raw_ptr ) ) )
, clone_fct ( other.clone_fct )
{}

template < typename D >
copy_ptr ( copy_ptr<D> const & other )
: raw_ptr ( static_cast<D*>( other.clone_fct( other.raw_ptr ) ) )
, clone_fct ( other.clone_fct )
{
non_polymorphic_class_error<T> d2;
}

// destruction frees the pointee
~copy_ptr ( void ) {
delete ( raw_ptr );
}

// assignment reduces to copy construction
// (for correctness and exception safety):
copy_ptr & operator= ( copy_ptr const & other ) {
copy_ptr dummy ( other );
swap( *this, dummy );
return( *this );
}

template < typename D >
copy_ptr & operator= ( copy_ptr<D> const & other ) {
copy_ptr dummy ( other );
swap( *this, dummy );
return( *this );
}

T const * operator-> ( void ) const {
return( raw_ptr );
}

T * operator-> ( void ) {
return( raw_ptr );
}

T const & operator* ( void ) const {
return( *( this->operator->() ) );
}

T & operator* ( void ) {
return( *( this->operator->() ) );
}

}; // copy_ptr<T>

Please, let me know what you think.


Best

Kai-Uwe Bux


 
Reply With Quote
 
Nindi73@yahoo.co.uk
Guest
Posts: n/a
 
      11-12-2006

Kai-Uwe Bux wrote:
> (E-Mail Removed) wrote:
> > A few days a ago I posted my code for a deep copy pointer which
> > doesn't require the pointee object to have a virtual copy constructor.
> > I need help with checking that it was exception safe and exception
> > neutral/
> > I got a reply from Bux with his code for a smart pointer with far fewer
> > lines of code
> > and more cleaner design, not over engineered like mine.
> >
> >

> http://groups.google.co.uk/group/com...e5c18bc6bb5c7e
> >
> >
> > However there was one possible extension to that code :
> >
> > 'The trade-off is that copy_ptr<Base> and copy_ptr<Derived> are
> > unrelated '
> > Kai-Uwe Bux
> > I think I have managed to implement this extension, so I post my code
> > here along with a main.cpp that exhibists the extension.

>
> What a coincidence, your post prompted me to rethink that, too. I appears
> that we arrived at very similar conclusions (see below).
>
>
> > Any comments about my abuse of the language would be more than welcome

>
> General comment: you lines are too long.
>

I apologise for the length of the lines, I think my problem is 2-fold.
Firstly I am not a proffesional developer
I have never really learnt a good style for code presentation, but I
suppose tools like doxygen make that a
non-excuse. Secondly, I think something just went wrong with the
pasting.
>
> > --------------------------------------------------------------------------------------------------------------
> > <smart_ptr_policies.h>
> > #ifndef SMART_POINTER_POLICIES_HEADER
> > #define SMART_POINTER_POLICIES_HEADER
> >
> >
> > #include<algorithm>
> > #include<boost/utility.hpp>
> > #include<boost/type_traits.hpp>
> >
> > //
> > http://groups.google.co.uk/group/com...hread/thread/b...
> >
> >
> >
> > template<class DerivedClass>
> > void * Buxclone(const void *theOtherPtr){
> > return new DerivedClass(*static_cast<const
> > DerivedClass*>(theOtherPtr));
> > }
> >
> >
> > template<class BaseClass>
> > struct BuxWrappedPointer {
> >
> > template<class T>
> > friend struct BuxWrappedPointer;
> >
> > BuxWrappedPointer():raw_pointer(0),theCloner(0){}
> >
> > template<class DerivedClass>
> > BuxWrappedPointer(DerivedClass * ptr):raw_pointer(ptr),
> > theCloner(&Buxclone<DerivedClass>){}
> >
> >
> > BuxWrappedPointer(const BuxWrappedPointer &theOther):
> > theCloner(theOther.theCloner),
> >
> > raw_pointer(theOther.clone(theOther.raw_pointer))
> > {}
> >
> > template<class MiddleBase>
> > BuxWrappedPointer(const BuxWrappedPointer<MiddleBase>
> > &theMiddleBase,
> > typename
> > boost::enable_if<boost::is_base_of<BaseClass,Middl eBase>,MiddleBase>::type
> > *pp=0):
> > theCloner(theMiddleBase.theCloner),
> > raw_pointer(static_cast<BaseClass

> *>
> > (theMiddleBase.theCloner(static_cast<const

> BaseClass
> > *>(theMiddleBase.raw_pointer)))){}
> >
> > BuxWrappedPointer<BaseClass> & operator=(const
> > BuxWrappedPointer<BaseClass> &theOther)
> > {
> > BuxWrappedPointer<BaseClass> temp(theOther);
> > std::swap(temp.raw_pointer,raw_pointer);
> > return *this;
> > }
> >
> >
> > BaseClass * raw_pointer;
> >
> >
> > ~BuxWrappedPointer(){delete raw_pointer;}
> > private:
> > BaseClass *clone(const BaseClass * theSource)const{
> > return static_cast<BaseClass*>(theCloner(static_cast<cons t
> > BaseClass*>(theSource)));
> > }
> > typedef void * (*clone_)(const void *);
> > clone_ theCloner;
> >
> >
> > };
> > #endif
> > --------------------------------------------------------------------------------------------------------------

>
> Oh boy, you are quite boost-savvy! I do not quite see, however, what all
> this enable_if< ... > stuff is doing for you. If it is just to get the
> right compiler errors if you do
>
> copy_ptr< Base > b_ptr = copy_ptr< NotDerived >( new not Derived() );
>
> then, I think, there are simpler means of going about it (see below). But I
> might be missing something here.
>


re enable_if from the boost website

The enable_if family of templates is a set of tools
to allow a function template or a class
template specialization to include or exclude itself
from a set of matching functions or
specializations based on properties of its template
arguments. For example, one can define
function templates that are only enabled for, and
thus only match, an arbitrary set of types
defined by a traits class. The enable_if templates
can also be applied to enable class template
specializations.

So I am only enabling
BuxWrappedPointer(const BuxWrappedPointer<MiddleBase>
&theMiddleBase)

when MiddleBase is derived FROM Base. This allows :
clone_ptr<MiddleBase> theMiddleClass_ptr(new Derived);
clone_ptr<Base> theBaseClass_ptr (theMiddleClass_ptr); //
casting up the hierachy should be allowed

but disallows everything else including
clone_ptr<Base> theBaseClass_ptr (new Derived);
clone_ptr<MiddleBase> theMiddleBaseClass_ptr
(theMiddleClass_ptr); // casting down the hierachy should NOT be
allowed


> > <smart_ptr.h>
> >
> > #ifndef SMART_POINTER__HEADER
> > #define SMART_POINTER__HEADER
> >
> > #include"smart_ptr_policies.h"
> >
> > template<
> > class BaseClass,
> > template <class> class CLONE_POLICY
> > >

> > class smart_ptr {
> > public:
> > typedef typename boost::remove_const<BaseClass>::type
> > non_const_base;
> >
> > template<class T,template <class> class CLONE_POLICY >
> > friend class smart_ptr;

>
> g++ gives me an error for the above saying that the declaration of
> CLONE_POLICY shadows the template parameter.
>
> >
> > template<class DerivedClass>
> > smart_ptr(DerivedClass *
> > theDerivedPointer_):theWrappedPointer(theDerivedPo inter_){}
> >
> > smart_ptr(const smart_ptr<non_const_base,CLONE_POLICY>&
> > theOtherSmart_ptr):
> >
> > theWrappedPointer(theOtherSmart_ptr.theWrappedPoin ter)
> > {}
> >
> > smart_ptr(const smart_ptr<const
> > non_const_base,CLONE_POLICY>&
> > theOtherSmart_ptr):
> > theWrappedPointer(theOtherSmart_ptr.theWrappedPoin ter)
> > {}
> >
> > template<class T>
> > smart_ptr(const smart_ptr<T,CLONE_POLICY>&
> > theOtherSmart_ptr,
> > typename
> > boost::enable_if<boost::is_base_of<non_const_base, typename
> > boost::remove_const<T>::type>,T>::type
> > *pp=0):
> > theWrappedPointer(theOtherSmart_ptr.theWrappedPoin ter)
> > {}
> >
> > smart_ptr(){}
> >
> > BaseClass *operator->()const{return
> > theWrappedPointer.raw_pointer;}
> >
> > virtual ~smart_ptr(){}

>
> Why is this destructor virtual?
>
> >
> >
> > private:
> > smart_ptr & operator=(const BaseClass *ptr);
> >
> > CLONE_POLICY<non_const_base> theWrappedPointer;
> >
> >
> > };
> >
> >
> > #endif

>
> Again, I find the boost stuff confusing. What design specs necessitate the
> use of non_const_base and remove_const?
>


This non_const_base gives me 'type' from 'const type'
So this allows me to do :
copy_ptr<Base> thePtr(new Derived);
copy_ptr<const Base> theConstPtr(thePtr);

Of course this may not be so important for deep copy but may be useful
for other policies. But I still want the Policy
class to be template on Base, even if the smart_ptr is templated on
Base or const Base, in some sense they are the same.

The line
template<class T>
smart_ptr(const smart_ptr<T,CLONE_POLICY>&

should be something like

template<class T, template <class> class OTHER_CLONE_POLICY>
smart_ptr(const
smart_ptr<T,OTHER_CLONE_POLICY>&

sorry, I use both Linux gcc and msvc, and I happend to be using msvc at
that moment, and it did not complain.

Again I am using the boost template stuff ONLY when T is derived FROM
Base, for same reasons as above. But I m ripping of the const of them
before I compare. That is

BaseClass = Base T = MiddleBase
This is ok
BaseClass = const Base T = MiddleBase
This is ok
BaseClass = Base T = const MiddleBase
This is ok
BaseClass = const Base T = const
MiddleBase This is ok




> > <main.cpp>
> > #include<vector>
> > #include<iostream>
> >
> > #include<cctype>
> > #include"smart_ptr.h"
> >
> > using namespace std;
> >
> >
> > class Base {
> > public:
> > Base():ch('*'){
> > Count++;
> > }
> > Base(const Base&):ch('*'){
> > Count++;
> > }
> > virtual char show(){
> > return ch;
> > }
> > virtual ~Base(){Count--;}
> > virtual void v()const=0;
> > static unsigned long Count;
> > private:
> > char ch;
> > };
> > unsigned long Base::Count(0);
> >
> > /// this will give us lots of derived classes
> > template<char ch_>
> > class Derived ublic Base {
> > public:
> > Derived():ch(ch_){
> > Count++;
> > }
> > Derived(const Derived<ch_>&):ch(ch_){
> > Count++;
> > }
> > virtual char show(){
> > return ch;
> > }
> > virtual ~Derived(){Count--;}
> > virtual void v()const{}
> > static unsigned long Count;
> > private:
> > char ch;
> >
> > };
> > template<char ch_>
> > unsigned long Derived<ch_>::Count(0);
> >
> > template<char ch_>
> > class DerivedSquared ublic Derived<ch_> {
> > public:
> > DerivedSquared():ch(std::tolower(ch_)){
> > Count++;
> > }
> > DerivedSquared(const DerivedSquared<ch_>&):ch(std::tolower(ch_)){
> > Count++;
> > }
> > virtual char show(){return ch;}
> > virtual ~DerivedSquared(){Count--;}
> > virtual void v()const{}
> > static unsigned long Count;
> > private:
> > char ch;
> >
> > };
> > template<char ch_>
> > unsigned long DerivedSquared<ch_>::Count(0);
> >
> >
> >
> >
> > int main() {
> >
> > smart_ptr<Derived<'B'>,BuxWrappedPointer> theDPA(new
> > DerivedSquared<'B'>);
> > cout << theDPA->show();
> >
> > smart_ptr<Base,BuxWrappedPointer> theDPA2(theDPA);
> > cout << theDPA2->show();
> >
> >
> > }

>
> I found that
>
> smart_ptr<int> i_ptr ( new int ( 5 ) );
> cout << *i_ptr << '\n';
>
> gives me an error. You should add operator*.
>


I completely agree, I should have posted a more complete class. But I
just wanted to show my extension to your trick
leaving out the other details. I intend to add other members too, such
as interoperability with auto_ptr etc


>
>
> I worked a little on the non-policy based version to have copy_ptr<Base> and
> copy_ptr<Derived> behave as desired. I also added a compile time check
> agains using non-polymorphic base classes. This might be overkill.
> (Alternatively, one could think about adding a deleter-function that would
> use the right destructor in any case.)
>
>
> #include <algorithm> // std::swap
>
> template < typename T >
> struct non_polymorphic_class_error {
> enum {
> trigger = sizeof( dynamic_cast<void*>( static_cast<T*>(0) ) )
> };
>
> };
>


I forbid myslef from using dynamic_cast, but I would have to try to
remeber the reasons why. But I do have a question.
Isn't it true that dynamic_cast happens at runtime and therefore we
have a overhead, whereas static_cast takes place at compile time, so
we don't. I think the boost is_base combined with boost enable_if lets
us 'error check' at compile time.


>
> // The clone function:
> // ===================
> template < typename T >
> void * clone ( void * ptr ) {
> return ( ptr == 0 ? 0
> : static_cast<void*>
> ( new T ( *( static_cast<T*>( ptr ) ) ) ) );
> }
>
> // The copy_ptr:
> // =============
>
> template < typename T >
> class copy_ptr {
>
> friend void swap ( copy_ptr<T> & p, copy_ptr<T> & q ) {
> std::swap( p.raw_ptr, q.raw_ptr );
> std::swap( p.clone_fct, q.clone_fct );
> }
>
> template < typename D >
> friend class copy_ptr;
>
> /*
> The idea is that in addition to a pointer, we also need
> a pointer to the _appropriate_ clone function.
> */
> T * raw_ptr;
> void * ( *clone_fct ) ( void * );
>
> public:
>
> copy_ptr ( T * ptr = 0)
> : raw_ptr ( ptr )
> , clone_fct ( clone<T> )
> {}
>
> template < typename D >
> copy_ptr ( D * ptr )
> : raw_ptr ( ptr )
> , clone_fct ( clone<D> )
> {
> non_polymorphic_class_error<T> d2;
> }
>
> // copy construction clones:
> copy_ptr ( copy_ptr const & other )
> : raw_ptr ( static_cast<T*>( other.clone_fct( other.raw_ptr ) ) )
> , clone_fct ( other.clone_fct )
> {}
>
> template < typename D >
> copy_ptr ( copy_ptr<D> const & other )
> : raw_ptr ( static_cast<D*>( other.clone_fct( other.raw_ptr ) ) )
> , clone_fct ( other.clone_fct )
> {
> non_polymorphic_class_error<T> d2;
> }
>
> // destruction frees the pointee
> ~copy_ptr ( void ) {
> delete ( raw_ptr );
> }
>
> // assignment reduces to copy construction
> // (for correctness and exception safety):
> copy_ptr & operator= ( copy_ptr const & other ) {
> copy_ptr dummy ( other );
> swap( *this, dummy );
> return( *this );
> }
>
> template < typename D >
> copy_ptr & operator= ( copy_ptr<D> const & other ) {
> copy_ptr dummy ( other );
> swap( *this, dummy );
> return( *this );
> }
>
> T const * operator-> ( void ) const {
> return( raw_ptr );
> }
>
> T * operator-> ( void ) {
> return( raw_ptr );
> }
>
> T const & operator* ( void ) const {
> return( *( this->operator->() ) );
> }
>
> T & operator* ( void ) {
> return( *( this->operator->() ) );
> }
>
> }; // copy_ptr<T>
>
> Please, let me know what you think.
>
>



I by no means am 'boost savy' I didn't even know about is_basr until a
few days ago. Its just that I find some real magical bits of
functionality there, its a waste of time trying to re-code some of it,
especially when the boost coders are in a far superior league to
of programmers to me. Also I prefer to do as much as possible at
compile time than at runtime.



N

PS I think my first ever use of is_base was to write this class.

 
Reply With Quote
 
Nindi73@yahoo.co.uk
Guest
Posts: n/a
 
      11-12-2006

Kai-Uwe Bux wrote:
> (E-Mail Removed) wrote:
> > A few days a ago I posted my code for a deep copy pointer which
> > doesn't require the pointee object to have a virtual copy constructor.
> > I need help with checking that it was exception safe and exception
> > neutral/
> > I got a reply from Bux with his code for a smart pointer with far fewer
> > lines of code
> > and more cleaner design, not over engineered like mine.
> >
> >

> http://groups.google.co.uk/group/com...e5c18bc6bb5c7e
> >
> >
> > However there was one possible extension to that code :
> >
> > 'The trade-off is that copy_ptr<Base> and copy_ptr<Derived> are
> > unrelated '
> > Kai-Uwe Bux
> > I think I have managed to implement this extension, so I post my code
> > here along with a main.cpp that exhibists the extension.

>
> What a coincidence, your post prompted me to rethink that, too. I appears
> that we arrived at very similar conclusions (see below).
>
>
> > Any comments about my abuse of the language would be more than welcome

>
> General comment: you lines are too long.
>
>
> > --------------------------------------------------------------------------------------------------------------
> > <smart_ptr_policies.h>
> > #ifndef SMART_POINTER_POLICIES_HEADER
> > #define SMART_POINTER_POLICIES_HEADER
> >
> >
> > #include<algorithm>
> > #include<boost/utility.hpp>
> > #include<boost/type_traits.hpp>
> >
> > //
> > http://groups.google.co.uk/group/com...hread/thread/b...
> >
> >
> >
> > template<class DerivedClass>
> > void * Buxclone(const void *theOtherPtr){
> > return new DerivedClass(*static_cast<const
> > DerivedClass*>(theOtherPtr));
> > }
> >
> >
> > template<class BaseClass>
> > struct BuxWrappedPointer {
> >
> > template<class T>
> > friend struct BuxWrappedPointer;
> >
> > BuxWrappedPointer():raw_pointer(0),theCloner(0){}
> >
> > template<class DerivedClass>
> > BuxWrappedPointer(DerivedClass * ptr):raw_pointer(ptr),
> > theCloner(&Buxclone<DerivedClass>){}
> >
> >
> > BuxWrappedPointer(const BuxWrappedPointer &theOther):
> > theCloner(theOther.theCloner),
> >
> > raw_pointer(theOther.clone(theOther.raw_pointer))
> > {}
> >
> > template<class MiddleBase>
> > BuxWrappedPointer(const BuxWrappedPointer<MiddleBase>
> > &theMiddleBase,
> > typename
> > boost::enable_if<boost::is_base_of<BaseClass,Middl eBase>,MiddleBase>::type
> > *pp=0):
> > theCloner(theMiddleBase.theCloner),
> > raw_pointer(static_cast<BaseClass

> *>
> > (theMiddleBase.theCloner(static_cast<const

> BaseClass
> > *>(theMiddleBase.raw_pointer)))){}
> >
> > BuxWrappedPointer<BaseClass> & operator=(const
> > BuxWrappedPointer<BaseClass> &theOther)
> > {
> > BuxWrappedPointer<BaseClass> temp(theOther);
> > std::swap(temp.raw_pointer,raw_pointer);
> > return *this;
> > }
> >
> >
> > BaseClass * raw_pointer;
> >
> >
> > ~BuxWrappedPointer(){delete raw_pointer;}
> > private:
> > BaseClass *clone(const BaseClass * theSource)const{
> > return static_cast<BaseClass*>(theCloner(static_cast<cons t
> > BaseClass*>(theSource)));
> > }
> > typedef void * (*clone_)(const void *);
> > clone_ theCloner;
> >
> >
> > };
> > #endif
> > --------------------------------------------------------------------------------------------------------------

>
> Oh boy, you are quite boost-savvy! I do not quite see, however, what all
> this enable_if< ... > stuff is doing for you. If it is just to get the
> right compiler errors if you do
>
> copy_ptr< Base > b_ptr = copy_ptr< NotDerived >( new not Derived() );
>
> then, I think, there are simpler means of going about it (see below). But I
> might be missing something here.
>
> > <smart_ptr.h>
> >
> > #ifndef SMART_POINTER__HEADER
> > #define SMART_POINTER__HEADER
> >
> > #include"smart_ptr_policies.h"
> >
> > template<
> > class BaseClass,
> > template <class> class CLONE_POLICY
> > >

> > class smart_ptr {
> > public:
> > typedef typename boost::remove_const<BaseClass>::type
> > non_const_base;
> >
> > template<class T,template <class> class CLONE_POLICY >
> > friend class smart_ptr;

>
> g++ gives me an error for the above saying that the declaration of
> CLONE_POLICY shadows the template parameter.
>
> >
> > template<class DerivedClass>
> > smart_ptr(DerivedClass *
> > theDerivedPointer_):theWrappedPointer(theDerivedPo inter_){}
> >
> > smart_ptr(const smart_ptr<non_const_base,CLONE_POLICY>&
> > theOtherSmart_ptr):
> >
> > theWrappedPointer(theOtherSmart_ptr.theWrappedPoin ter)
> > {}
> >
> > smart_ptr(const smart_ptr<const
> > non_const_base,CLONE_POLICY>&
> > theOtherSmart_ptr):
> > theWrappedPointer(theOtherSmart_ptr.theWrappedPoin ter)
> > {}
> >
> > template<class T>
> > smart_ptr(const smart_ptr<T,CLONE_POLICY>&
> > theOtherSmart_ptr,
> > typename
> > boost::enable_if<boost::is_base_of<non_const_base, typename
> > boost::remove_const<T>::type>,T>::type
> > *pp=0):
> > theWrappedPointer(theOtherSmart_ptr.theWrappedPoin ter)
> > {}
> >
> > smart_ptr(){}
> >
> > BaseClass *operator->()const{return
> > theWrappedPointer.raw_pointer;}
> >
> > virtual ~smart_ptr(){}

>
> Why is this destructor virtual?
>
> >
> >
> > private:
> > smart_ptr & operator=(const BaseClass *ptr);
> >
> > CLONE_POLICY<non_const_base> theWrappedPointer;
> >
> >
> > };
> >
> >
> > #endif

>
> Again, I find the boost stuff confusing. What design specs necessitate the
> use of non_const_base and remove_const?
>
> > <main.cpp>
> > #include<vector>
> > #include<iostream>
> >
> > #include<cctype>
> > #include"smart_ptr.h"
> >
> > using namespace std;
> >
> >
> > class Base {
> > public:
> > Base():ch('*'){
> > Count++;
> > }
> > Base(const Base&):ch('*'){
> > Count++;
> > }
> > virtual char show(){
> > return ch;
> > }
> > virtual ~Base(){Count--;}
> > virtual void v()const=0;
> > static unsigned long Count;
> > private:
> > char ch;
> > };
> > unsigned long Base::Count(0);
> >
> > /// this will give us lots of derived classes
> > template<char ch_>
> > class Derived ublic Base {
> > public:
> > Derived():ch(ch_){
> > Count++;
> > }
> > Derived(const Derived<ch_>&):ch(ch_){
> > Count++;
> > }
> > virtual char show(){
> > return ch;
> > }
> > virtual ~Derived(){Count--;}
> > virtual void v()const{}
> > static unsigned long Count;
> > private:
> > char ch;
> >
> > };
> > template<char ch_>
> > unsigned long Derived<ch_>::Count(0);
> >
> > template<char ch_>
> > class DerivedSquared ublic Derived<ch_> {
> > public:
> > DerivedSquared():ch(std::tolower(ch_)){
> > Count++;
> > }
> > DerivedSquared(const DerivedSquared<ch_>&):ch(std::tolower(ch_)){
> > Count++;
> > }
> > virtual char show(){return ch;}
> > virtual ~DerivedSquared(){Count--;}
> > virtual void v()const{}
> > static unsigned long Count;
> > private:
> > char ch;
> >
> > };
> > template<char ch_>
> > unsigned long DerivedSquared<ch_>::Count(0);
> >
> >
> >
> >
> > int main() {
> >
> > smart_ptr<Derived<'B'>,BuxWrappedPointer> theDPA(new
> > DerivedSquared<'B'>);
> > cout << theDPA->show();
> >
> > smart_ptr<Base,BuxWrappedPointer> theDPA2(theDPA);
> > cout << theDPA2->show();
> >
> >
> > }

>
> I found that
>
> smart_ptr<int> i_ptr ( new int ( 5 ) );
> cout << *i_ptr << '\n';
>
> gives me an error. You should add operator*.
>
>
>
> I worked a little on the non-policy based version to have copy_ptr<Base> and
> copy_ptr<Derived> behave as desired. I also added a compile time check
> agains using non-polymorphic base classes. This might be overkill.
> (Alternatively, one could think about adding a deleter-function that would
> use the right destructor in any case.)
>
>
> #include <algorithm> // std::swap
>
> template < typename T >
> struct non_polymorphic_class_error {
> enum {
> trigger = sizeof( dynamic_cast<void*>( static_cast<T*>(0) ) )
> };
>
> };
>
>
> // The clone function:
> // ===================
> template < typename T >
> void * clone ( void * ptr ) {
> return ( ptr == 0 ? 0
> : static_cast<void*>
> ( new T ( *( static_cast<T*>( ptr ) ) ) ) );
> }
>
> // The copy_ptr:
> // =============
>
> template < typename T >
> class copy_ptr {
>
> friend void swap ( copy_ptr<T> & p, copy_ptr<T> & q ) {
> std::swap( p.raw_ptr, q.raw_ptr );
> std::swap( p.clone_fct, q.clone_fct );
> }
>
> template < typename D >
> friend class copy_ptr;
>
> /*
> The idea is that in addition to a pointer, we also need
> a pointer to the _appropriate_ clone function.
> */
> T * raw_ptr;
> void * ( *clone_fct ) ( void * );
>
> public:
>
> copy_ptr ( T * ptr = 0)
> : raw_ptr ( ptr )
> , clone_fct ( clone<T> )
> {}
>
> template < typename D >
> copy_ptr ( D * ptr )
> : raw_ptr ( ptr )
> , clone_fct ( clone<D> )
> {
> non_polymorphic_class_error<T> d2;
> }
>
> // copy construction clones:
> copy_ptr ( copy_ptr const & other )
> : raw_ptr ( static_cast<T*>( other.clone_fct( other.raw_ptr ) ) )
> , clone_fct ( other.clone_fct )
> {}
>
> template < typename D >
> copy_ptr ( copy_ptr<D> const & other )
> : raw_ptr ( static_cast<D*>( other.clone_fct( other.raw_ptr ) ) )
> , clone_fct ( other.clone_fct )
> {
> non_polymorphic_class_error<T> d2;
> }
>
> // destruction frees the pointee
> ~copy_ptr ( void ) {
> delete ( raw_ptr );
> }
>
> // assignment reduces to copy construction
> // (for correctness and exception safety):
> copy_ptr & operator= ( copy_ptr const & other ) {
> copy_ptr dummy ( other );
> swap( *this, dummy );
> return( *this );
> }
>
> template < typename D >
> copy_ptr & operator= ( copy_ptr<D> const & other ) {
> copy_ptr dummy ( other );
> swap( *this, dummy );
> return( *this );
> }
>
> T const * operator-> ( void ) const {
> return( raw_ptr );
> }
>
> T * operator-> ( void ) {
> return( raw_ptr );
> }
>
> T const & operator* ( void ) const {
> return( *( this->operator->() ) );
> }
>
> T & operator* ( void ) {
> return( *( this->operator->() ) );
> }
>
> }; // copy_ptr<T>
>
> Please, let me know what you think.
>
>


Have been looking through your code and used this main.cpp

#include<iostream>

#include<cctype>
#include"copy_ptr.h"

using namespace std;


class Base {
public:
Base():ch('*'){
Count++;
}
Base(const Base&):ch('*'){
Count++;
}
virtual char show(){
return ch;
}
virtual ~Base(){Count--;}
virtual void v()const=0;
static unsigned long Count;
private:
char ch;
};
unsigned long Base::Count(0);

/// this will give us lots of derived classes
template<char ch_>
class Derived ublic Base {
public:
Derived():ch(ch_){
Count++;
}
Derived(const Derived<ch_>&):ch(ch_){
Count++;
}
virtual char show(){
return ch;
}
virtual ~Derived(){Count--;}
virtual void v()const{}
static unsigned long Count;
private:
char ch;

};
template<char ch_>
unsigned long Derived<ch_>::Count(0);

template<char ch_>
class DerivedSquared ublic Derived<ch_> {
public:
DerivedSquared():ch(std::tolower(ch_)){
Count++;
}
DerivedSquared(const DerivedSquared<ch_>&):ch(std::tolower(ch_)){
Count++;
}
virtual char show(){return ch;}
virtual ~DerivedSquared(){Count--;}
virtual void v()const{}
static unsigned long Count;
private:
char ch;

};
template<char ch_>
unsigned long DerivedSquared<ch_>::Count(0);




int main() {
char ch;

copy_ptr<Derived<'B'> > theDPA(new DerivedSquared<'B'>);
cout << theDPA->show();

copy_ptr<Base> theDPA2(theDPA);
cout << theDPA2->show();

cout << (*theDPA).show();
cout << (*theDPA2).show();

copy_ptr<const Base> theConstPtr(theDPA2);


cin >>ch;
}


I get an error with

copy_ptr<const Base> theConstPtr(theDPA2);

the error (in msvc) is

error C2682: cannot use 'dynamic_cast' to convert from 'const Base *'
to 'void *'

This may not be an issue for deep copy like I said previously, so I am
not sure if it is you requirement.

Just some other comments. As a personal preference, since there are two
main conponents to this class, the outwardly facing
part where on the BaseClass is involved and the internal part where
both BaseClass & DerivedClass are coming into play, to
break these apart , hence my policy.

If you decide to add the ability for const can you send me the code ?

Thnx
N

 
Reply With Quote
 
Kai-Uwe Bux
Guest
Posts: n/a
 
      11-12-2006
Posts are getting too long. Let's separate issues.

(E-Mail Removed) wrote:

>> template < typename T >
>> struct non_polymorphic_class_error {
>> enum {
>> trigger = sizeof( dynamic_cast<void*>( static_cast<T*>(0) ) )
>> };
>>
>> };
>>

>
> I forbid myslef from using dynamic_cast, but I would have to try to
> remeber the reasons why. But I do have a question.
> Isn't it true that dynamic_cast happens at runtime and therefore we
> have a overhead, whereas static_cast takes place at compile time, so
> we don't. I think the boost is_base combined with boost enable_if lets
> us 'error check' at compile time.


If you use

non_polymorphic_class_error< Base > dummy;

then there is a dummy variable that is never used. The compiler will
optimize that away. The dynamic_cast, however, will not be evaluated since
it sits within a sizeof expression. Those are not evaluated, instead the
compiler figures out the correct value magically.

Maybe the best way to check is just to put the line

sizeof( dynamic_cast<void*>( static_cast<Base*>(0) ) );

somewhere. It evaluates to a const-expression without side-effects and
therefore should not create any code.


Best

Kai-Uwe Bux
 
Reply With Quote
 
Nindi
Guest
Posts: n/a
 
      11-14-2006

Kai-Uwe Bux wrote:
> Posts are getting too long. Let's separate issues.
>
> (E-Mail Removed) wrote:
>
> >> template < typename T >
> >> struct non_polymorphic_class_error {
> >> enum {
> >> trigger = sizeof( dynamic_cast<void*>( static_cast<T*>(0) ) )
> >> };
> >>
> >> };
> >>

> >
> > I forbid myslef from using dynamic_cast, but I would have to try to
> > remeber the reasons why. But I do have a question.
> > Isn't it true that dynamic_cast happens at runtime and therefore we
> > have a overhead, whereas static_cast takes place at compile time, so
> > we don't. I think the boost is_base combined with boost enable_if lets
> > us 'error check' at compile time.

>
> If you use
>
> non_polymorphic_class_error< Base > dummy;
>
> then there is a dummy variable that is never used. The compiler will
> optimize that away. The dynamic_cast, however, will not be evaluated since
> it sits within a sizeof expression. Those are not evaluated, instead the
> compiler figures out the correct value magically.
>
> Maybe the best way to check is just to put the line
>
> sizeof( dynamic_cast<void*>( static_cast<Base*>(0) ) );
>
> somewhere. It evaluates to a const-expression without side-effects and
> therefore should not create any code.

I am not sure how it can do this, isn't dynamic_cast a runtime
evaluation ?

>
>
> Best
>
> Kai-Uwe Bux


 
Reply With Quote
 
Nindi
Guest
Posts: n/a
 
      11-14-2006

Gianni Mariani wrote:
> (E-Mail Removed) wrote:
> > A few days a ago I posted my code for a deep copy pointer which
> > doesn't require the pointee object to have a virtual copy constructor.
> > I need help with checking that it was exception safe and exception
> > neutral/
> > I got a reply from Bux with his code for a smart pointer with far fewer
> > lines of code
> > and more cleaner design, not over engineered like mine.
> >
> > http://groups.google.co.uk/group/com...e5c18bc6bb5c7e
> >
> >
> > However there was one possible extension to that code :
> >
> > 'The trade-off is that copy_ptr<Base> and copy_ptr<Derived> are
> > unrelated '
> > Kai-Uwe Bux
> > I think I have managed to implement this extension, so I post my code
> > here along with a main.cpp that exhibists the extension.

>
> Why do you need such a beast ? i.e. what are the requirements and use case ?


I DID know, I am trying to remember why I needed this, after a while it
just became a curious exercise.



>
> >
> > Any comments about my abuse of the language would be more than welcome

>
> It's kind of hard to read.


 
Reply With Quote
 
Earl Purple
Guest
Posts: n/a
 
      11-14-2006

(E-Mail Removed) wrote:
> A few days a ago I posted my code for a deep copy pointer which
> doesn't require the pointee object to have a virtual copy constructor.


Just as well given that there is no such thing as a virtual
constructor.

class A
{
public:
virtual A( const A & ); // illegal. Constructors can't be virtual
};

< rest snipped >

 
Reply With Quote
 
Nindi
Guest
Posts: n/a
 
      11-14-2006

Earl Purple wrote:
> (E-Mail Removed) wrote:
> > A few days a ago I posted my code for a deep copy pointer which
> > doesn't require the pointee object to have a virtual copy constructor.

>
> Just as well given that there is no such thing as a virtual
> constructor.
>
> class A
> {
> public:
> virtual A( const A & ); // illegal. Constructors can't be virtual
> };
>


NO what I meant by a virtual copy constructor is something like this

virtual Base * copy()const=0;

and then implemented in derived classes like this


Derived * copy()const{return new Derived(*this);}

http://www.parashift.com/c++-faq-lit....html#faq-20.8

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
template copy constructor vs normal copy constructor cinsk C++ 35 10-10-2010 11:14 PM
Smart Pointer showing deep copy semantics arijit79@gmail.com C++ 2 12-25-2008 03:43 PM
what is Deep Copy, shallow copy and bitwises copy.? saxenavaibhav17@gmail.com C++ 26 09-01-2006 09:37 PM
is dict.copy() a deep copy or a shallow copy Alex Python 2 09-05-2005 07:01 AM
deep/shallow copy - constructor v Object.copy() VisionSet Java 8 04-29-2004 10:41 PM



Advertisments