Topic: Proposal for clone library function


Author: Brian Parker <bparker@gil.com.au>
Date: 1996/12/05
Raw View
The following are some thoughts I have had on some extensions to the
standard library. Though it is probably too late to incorporate any of these
suggestions
into the current standard, I would be interested in any comments.

(1) Proposal to add virtual constructor functions to the standard library
-------------------------------------------------------------------------
In D&E p317, Dr Stroustrup anticipates the extension of the type_info class
in implementation-
specific ways to add, amongst other type-specific features, functions for
creating and copying
objects. I propose that this function be added as follows-

class type_info {

 ... rest as per the draft standard

 virtual void* clone(const void* const p) const = 0;
};

where clone() is overridden for the type that the type_info represents such that
clone() copy-constructs a copy of p on the heap

e.g. for type_info representing type T, this would be overridden by the
implementation as
something like...

T* type_info::clone(const void* const p) const
{
 return new T(*(const T* const)p); // undefined behaviour if p not a T*
}

If the copy constructor of the object is inaccessible a function that
returns a null pointer
could be generated instead.

(As an aside, I have a question/comment about covariant return types.
As written, I believe this function is incorrect according to the draft std
as the covariant
return type must be derived from the return type of the base class, but in
the spirit of
void* being viewed as the base of all pointers (i.e. all pointers can be
implicitly
cast to void*) might it not be more consistent to allow derived class return
types of any
pointer type to override void* returns in the base class?
In any case, this doesn't impact the above proposal; just define the
functions to return void*
and later (safetly) cast the returned void*.)

Given the above function, one can now define the following global (in std
namespace) template
function-

// return new heap copy of object pointed to by ptr
template<class T>
T* clone_ptr(const T* const ptr)
{
 return typeid(*ptr).clone(ptr);
}

In fact, perhaps only this global function should be standardized and the
definition of
the member function in the type_info class could be left as implementation
detail.

The point is that this extension should be trivial to implement given that
type_info already
needs to be implemented, and it should add minimal code size; certainly
type_info::name()
would require more code than this function.

What is the use of this global function?
Without it, the only way one can emulate a virtual copy constructor is to
add a virtual
clone() member to the base class of any class hierarchy that needs this
functionality and ensure
that all derived classes override it correctly; if they don't, run-time
errors will ensue.
The major problem, however, is that one cannot write generic template
classes that
can be instantiated with any polymorphic type if it requires virtual
constructor functionality;
only classes that inherit a virtual clone() function can be used.

For example, polymorphic smart pointer classes with value semantics and
envelope/letter classes
using copy-on-write fall into this category.

e.g.

// smart pointer with value semantics that points to a T or an object
derived from T
template<class T>
smart_ptr{
public:
 ...

 smart_ptr(const smart_ptr<T>& ptr):
 p_(ptr.p_->clone()){} // This template can only be used for T's with
clone() defined.
    // If clone_ptr() was available, this function could be written
    // to work with any polymorphic type with an accessible copy
    // constructor

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

 ...

 T* p_;
};


(Another minor advantage of the clone_ptr() template function is that it can
be specialised for
non-polymorphic and built-in types (with the obvious trivial
implementations) so the same smart
pointer code could be usable with both polymorphic and non-polymorphic types)

(N.B. As well as the clone_ptr() function discussed above, it may also be
useful to add
a create_ptr() function which is similar but creates a default-constructed
object instead of
a copy. However, I am uncertain how useful this would be.)

(2) Smart pointer proposal:
---------------------------
If the above proposal was adopted, more generic smart pointer and other
template classes would be
possible. This, combined with the other improvements in smart pointer
functionality due to
member templates etc., makes standardising further smart pointer classes
worthwhile.

(In fact, most of the objections raised in D. Edelson "Smart pointers:
They're smart but they're
not pointers" appear to be answered in draft ISO C++).

I suggest that two further smart pointers be defined in addition to the
current auto_ptr.

The first is a polymorphic smart pointer class with value semantics (ala
Barton & Nackman's
CloneableObjPtr). This would be particularly useful for heterogeneous
containers in STL.
STL is most useful with types with value sematics but polymorphism dictates
using pointers.
CloneableObjPtr combines both characteristics and allows one to avoid having
to develop custom
envelope classes to achieve the same effect.

The second is a reference-counted smart pointer class (ala Barton &
Nackman's CountedObjPtr).
This is, of course, useful for automatic garbage collection of shared
objects and would be
useful for porting code from evironments with reference semantics (e.g.
Eiffel, Java).
(I note that this has been suggested for standardisation before in this
newsgroup)

The specifications of these classes are fairly simple and based on those
found in
Barton & Nackman's text.

The fact that most advanced C++ texts present their own variations of these
smart pointer
types indicates their usefulness and need for standardisation. Also,
although they are useful,
they are more advanced constructs which C++ novices may not be aware of unless
they are available in the standard library.


,Brian Parker.
(bparker@gil.com.au)
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]