Boost logo

Boost Users :

From: todd (todd_at_[hidden])
Date: 2004-02-08 13:18:16


On Sun, 08 Feb 2004 20:47:41 +0000, Steve Folly wrote
> Hmmm... I've looked at our other posts in this thread and I don't
> think I've really explained my problem:

Actually, I think you explained the problem quite well.

> I initially wanted to use shared pointers to not have to worry about
> memory deallocation.

Yes. All smart pointers serve this purpose.

> [please ignore syntax errors!]

ditto.

class statement: public ref_counted
{
public:
   virtual void execute() = 0;
};

typedef intrusive_ptr<statement> statement_p;

// Look at this trick :)
typedef intrusive_ptr<class block_statement> block_statement_p;

class block_statement : public statement
{
public:
   block_statement ();
   block_statement_p add( statement_p s )
   {
       statements.push_back( s );
       return this; // conversion is implicit
   }

private:
   std::list<statement_p> statements;
};

typedef intrusive_ptr<class if_statement> if_statement_p;

class if_statement : public statement
{
public:
   if_statement ( expression_p );

   if_statement_p then_( statement_p s )
   {
       then_statement = s;
       return this;
   }

   if_statement_p else_( statement_p s )
   {
       else_statement = s;
       return this;
   }

private:
   statement_p then_statement;
   statement_p else_statement;
};

// helper functions

block_statement_p block_()
{
   return new block_statement(); // conversion is implicit
}

if_statement_p if_( expression_p e )
{
   return new if_statement( e ); // conversion is implicit
}

// same as what you had...
block_p b = block_()
           ->add(
               if_( expression )
                   ->then( stmt2 )
                   ->else( stmt3 )
           )
           ->add(
               if_( expression )
                   ->then( stmt2 )
                   ->else( stmt3 )
           );

> My dilemma is - what do block_statement::add, if_statement::then and
> if_statement::else return? Since they have no knowledge of the shared
> pointer, the best they can do is to return 'this', but block_statement::add
> is expecting the shared pointer?

intrusive_ptr can be declared on a class that hasn't been defined yet. The
functions shoud return an intrusive_ptr. I think I said earlier that they
could return normal pointers; if so I made a mistake. That *might* cause
premature deletion; the standard doesn't place a strong enough guarantee on
the order of operations. i.e. a temporary intrusive_ptr might be destructed
before another is constructed if those member functions return normal pointers.

The call to add() in the example above automatically converts the
intrusive_ptr<if_statement> to an intrusive_ptr<statement>; shared_ptr can't
do that. This assumes that you are using a recent compiler.

A caveat: don't be tempted to do the following, now that you know about the
implicit conversions:

block_p b = (new block_statement)
           ->add(
               (new if_statement( expression ) )
                   ->then( stmt2 )
                   ->else( stmt3 )
           )
           ->add(
               ( new if_statement( expression ) )
                   ->then( stmt2 )
                   ->else( stmt3 )
           );

It will compile and run, but it may leak memory if an exception is thrown.

Todd


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net