
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