Boost logo

Boost :

From: Beman Dawes (bdawes_at_[hidden])
Date: 2002-01-05 15:38:52


At 04:04 PM 1/4/2002, Andrei Alexandrescu wrote:

>> Regardless of the exact technique used, I don't see how we can use the
>Loki
>> SmartPtr as the base (or typedef template when that becomes available)
>for
>> the Boost smart pointers without doing something to increase
inter-policy
>> communication.
>
>I think inter-policy communication would be good, but there are two
points
>I'd like to make. One is that supporting arrays is the wrong aim to shoot
>for. The second is that the mechanism with independent policies has
proven
>very flexible so far, and that alternate mechanisms need to bring a lot
of
>bang to justify their added complexity. Let me detail my points below.
>
>Support for arrays already exists in SmartPtr to a certain extent. You
can
>easily write a policy that implements Destroy() by calling delete[].
Then,
>you can index into the array by calling GetImpl(sp). For example:
>
>SomeSmartArrayPtr sp;
>...
>GetImpl(sp)[5] = 0;
>
>The obvious objection is that true support for arrays means providing an
>indexing operator. Actually an earlier SmartPtr implementation did
support
>that, but in the end I decided to drop it.
>
>The problem is that smart pointers seldom point to arrays, and when they
>do,
>you use them only as back-end in a more elaborate data structure (such as
a
>full-fledged array itself) rather than a prima donna array. (How did that
>line sound? Ah, "If you want arrays, use std::vector.") When you think of
>implementing indexing for a smart pointer, checking index boundaries
>immediately comes to mind and before you know it, you are talking about
>implementation of full-blown arrays!
>
>That's why I decided to leave in only Spartan array support, without
>support
>for indexing. The bad thing with "nice-to-have" features is that the list
>can go on and on and on. You have to define your design's boundaries.
Smart
>pointers are not arrays. If one wants arrays, she can implement an array
>using SmartPtr as a building block. I think this is only fair and
>reasonable.

While I understand the arguments above, I also see direct use of a policy
based smart pointer as a tool for intermediate to advanced programmers. At
least for this group, I'm willing to "trust the programmer."

I'm also concerned that the current design doesn't really support any
feature which (like arrays) requires an interface change. The forwarding
functions in the SmartPtr framework class essential define the
interface. A StoragePolicy, for example, could add a new form of access,
but there wouldn't be any way to invoke the proper CheckingPolicy function
from it.

>My second point was that a design with orthogonal policies is simplest
and
>should be strived for.

I don't think it is simplest - the lack of communication between policies
requires more work in the SmartPointer framework itself, such as forwarding
functions.

A simplified example, current multiple inheritance approach
-----------------------------------------------------------

template< class T >
class default_store_policy {
   ...
   PointerType get() { return pointee__; }
   };

template< class P >
class default_check_policy {
   ...
   void check( P val ) { assert( Val ); }
   };

template< class T,
           template<class> class StorePolicy=default_store_policy,
           template<class> class CheckPolicy=default_check_policy >
class SamplePtr
   : public StorePolicy<T>,
   , public CheckPolicy<typename StorePolicy<T>::PointerType> {
   ...
   PointerType get() {
     check( SP::get() );
     return SP::get();
     }
   };

Same example, nested inheritance approach
-----------------------------------------

template< class T >
class default_store_policy {
   ...
   PointerType get() { return pointee__; }
   };

template< class B >
class default_check_policy {
   ...
   PointerType get() { assert( B::get() ); return B::get(); }
   };

template< class T,
           template<class> class StorePolicy=default_store_policy,
           template<class> class CheckPolicy=default_check_policy >
class SamplePtr
   : public CheckPolicy< StorePolicy< T > > {
   ...
   };

Isn't the nested inheritance approach a bit simpler? And more flexible,
too. Or am I missing something?

>I recall you once said SmartPtr is too complicated. Now it seems it's too
>simple. Guess that's a good sign :o).

I think what I said was that the template interface, because of the number
of relatively complex parameters, was too complicated for everyday use. I
think that issue can be resolved by providing typedef templates or
equivalent for common uses like shared_ptr and scoped_ptr.

--Beman


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk