Boost logo

Boost :

From: Jaap Suter (J.Suter_at_[hidden])
Date: 2002-06-22 14:57:33


Hello,

I'm implementing a generic quad-linked tree structure and currently working
on ownership policies. Basically, I want the user tree to choose among three
ownership-types.

First there is raw ownership, which means that if a tree-node is deleted,
nothing is done with it's children. This corresponds with raw pointers to
the children.

The second is scoped ownership, which means a node deletes its children upon
deletion. This corresponds with boost::scoped_ptr's to the children.

The third is shared ownership, which means a node has boost::shared_ptr's to
the children.

Since template< template > parameters are not possible yet (intermezzo: is
it true that this is under discussion at the moment?) I've decided to use
the following construct:

template < unsigned int t_OwnershipPolicy >
class Node
{
    BOOST_STATIC_CONSTANT( unsigned int, RAW = 0 );
    BOOST_STATIC_CONSTANT( unsigned int, SHARED = 1 );
    BOOST_STATIC_CONSTANT( unsigned int, SCOPED = 2 );

    BOOST_STATIC_ASSERT( t_OwnerShipPolicy < 3 );

    // This is implemented using template-meta programming, but written with
    // regular if-statements (pseudo-code-ish) for clarity:
    if ( t_OwnerShipPolicy == SHARED )
        typedef boost::scoped_ptr< Node > NodePtr;
    else
    if ( t_OwnerShipPolicy == SCOPED )
        typedef boost::shared_ptr< Node > NodePtr;
    else
    if ( t_OwnerShipPolicy == RAW )
        typedef Node* NodePtr;

    // Container structure is more complex in my
    // code (because of the quadlink) but that doesn't
    // matter for the purpose of this email.
    std::some_container< NodePtr > m_Children;
}

This works fine in general, although I do wonder about the design-elegancy
of this construct. If anybody has any better idea I would love to hear it,
although that is more appropriate for comp.lang.c++.moderated I think.

However, on with the question...

Problems arise when I implement a certain GetLeftMostChild() method that
should return a raw pointer. Because I don't allow implicit conversions in
boost's smartpointers I have to apply .get() to them in order to obtain the
raw pointer.

This means that when NodePtr equals a raw pointer, the implementation
becomes:

Node* GetLeftMostChild()
{
    return m_Children[ 0 ]; // Or whatever container acces I used;
}

Whereas the shared_ptr and scoped_ptr implementation becomes:

Node* GetLeftMostChild()
{
    return m_Children[ 0 ].get(); // Or whatever container acces I used;
}

Obviously I need to resolve this conflict. So what I've done is implemented
a raw_ptr class that implements the .get() method so that it is compatible
with the shared_ptr and scoped_ptr. So now the line that used to be:

if ( t_OwnerShipPolicy == RAW ) typedef Node* NodePtr;

becomes:

if ( t_OwnerShipPolicy == RAW ) typedef raw_ptr< Node > NodePtr;

And I can implement all my methods in the same way cause all ownership-types
implement the same interface.

Now the question is:

What is wrong? Either my design is wrong (probably) or
could the boost::smart_ptr collection use a new boost::raw_ptr in addition
to the already existing pointer types?

Probably my ownership-design is flawed (in which case my question should be
posted in comp.lang.c++.moderated instead, sorry about that), and otherwise
I think this clearly shows that boost needs a policy-based smartpointer
instead of the multitude of pointers that exist right now (imho the addition
of weak_ptr signalled this already). But if policy-based smartpointers
remain absent, then is the addition of a boost::raw_ptr a good idea or not?

It's probably an addition taking 5 minutes of coding (and 6 weeks on the
discussion of whether implicit conversions are ok with raw_ptr's, after all,
they are raw already :) hehe).

Cheers and thanks,

Jaap Suter
http://jaap.flipcode.com


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