
"Pavol Droba" <droba@topmail.sk> wrote in message news:20041008185302.GN1510@lenin.felcer.sk... | Hi Thorsten, | | On Fri, Oct 08, 2004 at 08:11:28PM +0200, Thorsten Ottosen wrote: | > Then I compared code like | > | > for_each(.ptr_container_with_null_objects ) | > { | > i->foo(); // non-virtual | > i->bar(); // virtual | > } | > | > with | > | > for_each( standard_container_with_0s ) | > { | > if( *i ) | > { | > (*i)->foo(); // non-virtual | > (*i)->bar(); // virtual | > } | > } | > | > on vc7.1 | > | > In this setting a if the we have 2 : 5 nulls (2 nulls, 3 normal), checking for | > 0 wins. If we have 1 : 5 nulls or better | > the null object method wins. Basically I would guess this ratio depends | > entirely on how many if() we can execute for each virtual function | > dispatch since the body of null-object function is always trivial. | > | > Conclusion: disallowing 0 will not only lead to simpler, safer programs, but | > it will probably also boost performance. | | I'm sorry, but I must disagree with you analysis. You are looking to the problem | only from the smart containers perspective. This leads to fundamentaly wrong assumptions | and wrong results. | | Lets us think for a while what is the difference between null_object and 0 pointer. | | If we want to apply your semantics, null object must have fully defined interface. | Although its function will probably do nothing, still they must behave correctly. | So it is no longer a null_object. It is an object with a special state. I don't understand why you can't give it special state; IMO it is not necessary, though. | If you relax this requiremnt you will get to the exactly same scenario as with 0 | poiner, only with slightly bigger overhead. Why? Becase if I designate something | as null, I will have to check for it anyway. So your example will look like this: | | for_each(.ptr_container_with_null_objects ) | { | if(!i->is_null) | { | i->foo(); // non-virtual | i->bar(); // virtual | } | } do you mean a dynamic cast? or how do ->is_null look like? | Otherwise, you will have pay the comparison cost every time you perform an operation | on the null object, and that might be on far more places. not understood. | In other words. If I designate an object as null, I want to threat it as an invalid | null object. Therefor I will have to check every operation I would with 0 pointer. that's not what null objects are for. | Also, if the design of my application needs to put only non-null objects into the container, | I will NOT HAVE to check anything. true, but you have lost the guarantee. Thus any interface with ptr_container foo(); bar( const ptr_container& r ); you have to document explicitly whether you allow null or not. | At most I will put asserts there, but definitely not | exceptions. by "there" you mean where? | So your arguments are quite misleading. If you allow 0 pointers, it is still possible | to uses null_object pattern without any additional cost. The oposite is obviosly not | feasible. I need some real code to work with to be able to see this. Then I can rewrite it to compare. br Thorsten