Boost logo

Boost :

From: Thorsten Ottosen (nesotto_at_[hidden])
Date: 2004-10-08 14:25:21


"Pavol Droba" <droba_at_[hidden]> wrote in message
news:20041008185302.GN1510_at_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


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