From: Peter Dimov (pdimov_at_[hidden])
Date: 2003-09-11 10:27:33


Richard Hadsell wrote:
> Daniel Frey wrote:
>
>> ...
>> if (ptr.get()) ...
>> if (ptr) ... // Less efficient.
>> ...
>> As I think that efficiency is more important than a nice error
>> message, I'd like to propose changing shared_ptr's code appropriately
>> to avoid the overhead imposed by the current safe-bool-idiom.
>> Comments?

The two 'almost bool' idioms are not equivalent. Providing a single
conversion to "unspecified bool type" allows for example code like:

void f(bool);
void f(int);

f(p);

to compile. I'm not sure yet whether this is a good thing or not. I think
that at one point I convinced myself that it is good, but I can't remember
the details. I tend to favor the 'single conversion to unspecified boolean
type' approach from a specification point of view, too.

> I was interested in this thread, because I use scoped_ptr and
> scoped_array extensively, and performance is important for my
> application. I was glad to see the bool operator added to those
> classes, and I laboriously changed all my 'if (ptr.get())'s to 'if
> (ptr)', not realizing the compiler might not generate code as
> efficient.
>
> Is it true that the discussion applies to the scoped_ classes as well
> as shared_ptr? And is someone willing to fix them, too?

I think that the actual difference is small to nonexistent, but if this
issue is considered important, we can switch from a member function pointer
to a data member pointer as the unspecified bool type. It is as efficient as
a plain operator bool, at least on the compiler I tried:

operator T * this_type::*unspecified_bool_type() const:

    mov eax, DWORD PTR _pv$[esp-4]
    mov ecx, DWORD PTR [eax]
    neg ecx
    sbb ecx, ecx
    test ecx, OFFSET FLAT:?get@?$shared_ptr_at_X@boost@@QBEPAXXZ ;
boost::shared_ptr<void>::get
    je SHORT $L5261

operator bool:

    mov eax, DWORD PTR _pv$[esp-4]
    cmp DWORD PTR [eax], 0
    je SHORT $L5240

operator T * this_type::*unspecified_bool_type:

    mov eax, DWORD PTR _pv$[esp-4]
    cmp DWORD PTR [eax], 0
    je SHORT $L5261

All code for

    if(pv)

This improvement has been first suggested by Daveed Vandevoorde. I haven't
applied it to the smart pointers since "if it's not broken don't fix it" but
perhaps the time has come to do so.