Boost logo

Boost :

From: Fernando Cacciola (fcacciola_at_[hidden])
Date: 2001-09-20 14:35:11


----- Original Message -----
From: Douglas Gregor <gregod_at_[hidden]>
To: <boost_at_[hidden]>
Sent: Thursday, September 20, 2001 4:15 PM
Subject: Re: [boost] Re: More on the optional class.

> On Wednesday 19 September 2001 02:08, you wrote:
> > I've been playing with the safe_bool technique -taken from
> > function_base.hpp- and I've found the following:
> >
> > I've used the following test bed.
> >
> > In this test there is a class A with either 'operator bool()' or
'operator
> > safe_bool()'.
> > I can switch between operators by commenting out one of them.
> > Following the class declaration there is a set of test cases. Each test
is
> > contained within one of two macros:
> > PASSED() or FAILED().
> > I can switch between macros by commenting out one of them.
> >
> > With operator bool(), all test passed.
> > With operator safe_bool(), only the tests that are inside PASSED() in
the
> > code below passed.
> >
> > PASSED(
> > file://FAILED(
> > bool compare_to_const_int ()
> > {
> > const int null = 0 ;
> > A a ;
> > return a == null ;
> > }
> > )
>
> I'm not sure what compiler you used, but this should fail (and does, on
both
> GCC 3.0 and Comeau 4.2.45.2 in their strictest modes).
>
I see.

> >
> > As you can see, all conversions to bool were accepted, except the one
> > required to allow the explicit comparison with a bool value.
> > Notice that a conventional 'operator bool()' also accepts all the int
> > conversions because of the allowed promotion from bool to int.
>
> Ok.
>
> > Notice also that the comparison to the literal 0 (not literal 1) and the
> > comparison to a const int (with value 0) are allowed.
>
> Literal 0 compares, const int (with value zero) should not.
>
I see.

> > Of course, this is the expected behavior, otherwise the expressions if
 A
> > ) / if ( A == 0 ) wouldn't compile.
>
> "if (A)" is definitely desirable, though I'm not sure if "if (A == 0)" is
> desirable.
>
I'm inclined to think that (A==0) is not desirable.

> > safe_bool is a pointer (to a member function), thus it is allowed to
> > compare with a null pointer value and it is allowed to decay into bool.
> >
> > If I change safe_bool from a member function pointer into a regular
pointer
> > (int const*), all the same tests passed except 'compare_with_const_int'
> > (pretty odd).
> >
> > It all means that safe_bool is safer than 'operator bool()', but not
safer
> > than 'operator T const*' (when the later is applicable).
>
> I disagree with this. Peter Dimov chose to use a member pointer
specifically
> because they do not allow pointer arithmetic or ordering. If one uses a
> conversion to a pointer, expressions such as "A + 2", "A++", and "A < B"
must
> also be poisoned.

Oh yes, you are right, I overlooked that.

>
> > If safe_bool is going to be added to utility.hpp I think these results
> > should be documented.
>
> All possible side effects will be documented.
>
> > In the particular case of optional<T>, the allowed conversion to bool
> > prevents this technique to be applicable.
>
> I'm not sure I understand this, but I'm also not familiar with
optional<T>.
>
The conversion to bool allowed by safe_bool might allow the following:

optional<bool> foo();
void bar()
{
   bool b = foo() ;

   // this will compile OK, but it is an error because the value of 'b'
won't be the bool value
   // contained in the result of 'foo' -which is what the user would expect-
   // but the boolean condition corresponding to the initialized state of
foo's result.
}

> > It seems to me that (!,!!) and get(opt) are still the only truly safe
> > choices. (and then the poison ==,!= are not required)
>
> I think there are safe choices. Just be using the member pointer we narrow
> the set of operations to:
>
> a == b
> a != b
> a == 0
> a != 0
> 0 == a
> 0 != a
>
> The first two are clearly a problem, and should be poisoned. The other
four
> may or may not be problem, but can likewise be poisoned. A
bool-convertible
> class Foo would be defined as:
>
> class Foo : boost::bool_convertible<Foo> {
> public:
> operator safebool() const { /* .. */ }
> safebool operator!() const { /* ... */ }
> };
>
> where:
>
> template<typename T>
> class bool_convertible {
> friend void operator==(const Foo&, const Foo&);
> friend void operator!=(const Foo&, const Foo&);
> friend void operator==(const int, const Foo&);
> friend void operator!=(const int, const Foo&);
> friend void operator==(const Foo&, const int);
> friend void operator!=(const Foo&, const int);
> };
>
>
I like the above.
I just realized that I don't want optional<T> to be bool convertible. I want
it to allow *only* something like if ( opt ), but that seems to require a
bool conversion, even a very restricted one.

Fernando Cacciola
Sierra s.r.l.
fcacciola_at_[hidden]
www.gosierra.com


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