Index: libs/utility/operators.htm =================================================================== RCS file: /cvsroot/boost/boost/libs/utility/operators.htm,v retrieving revision 1.12 diff -u -r1.12 operators.htm --- libs/utility/operators.htm 4 Nov 2002 01:59:31 -0000 1.12 +++ libs/utility/operators.htm 12 Mar 2003 19:08:13 -0000 @@ -340,6 +340,8 @@
  • indexable<>
  • +
  • bool_testable<>
  • +
  • Any composite operator template that includes at least one of the above
  • @@ -528,6 +530,17 @@ + bool_testable<T> + + bool operator!(const T&) + + static_cast<bool>(t).
    + T convertible to bool. See the bool_testable Note. + + + addable<T>
    addable1<T> @@ -974,7 +987,123 @@ that don't implement the NRVO.

    +

    Bool Testable Note

    + +

    bool_testable provides the + opposite of operator bool, such that the expression if (!p) is + valid, whilst also making operator bool safer by preventing + accidental conversions to integer types. If operator bool + were declared without using + bool_testable then expressions + such as :

    + +
    +void f(int);
    +
    +void g(object o)
    +{
    +    f(o);
    +}
    +
    + +

    would compile silently, not warning the user of the (probably) + unintended behaviour of passing 0 or 1 to + f().

    bool_testable<> prevents these + accidental conversions by declaring an operator signed char() + private, and not defining the body.

    + +
    Example :
    + +
    +class Stream : boost::bool_testable<Stream>
    +{
    +public:
    +    explicit Stream(const char * source);
    +    operator bool() const;
    +    // non-member bool operator!(const T&) const auto-generated and 
    +    // operator bool made safe by bool_testable<>
    +
    +    bool can_print();
    +};
    +
    +void g(int);
    +
    +void f()
    +{
    +    if (Stream s1("source.txt"))
    +    {
    +        // use s1 ...
    +    }
    +
    +    // or..
    +
    +    Stream s2("source.txt");
    +    if (!s2)
    +    {
    +        // handle problem
    +    }
     
    +    // or ..
    +
    +    if (s2 && s2.can_print()) // see note
    +    {
    +        // print something...
    +    }
    +
    +    g(stream); // Will not compile, but would compile 
    +               // fine without bool_testable<>
    +}
    +
    + +
    Note for MSVC version 6 users :
    + +

    Due to a bug in MSVC6, whilst compiling the above code, the compiler + will incorrectly complain of 'ambiguous operator &&' at + line 30. The workaround for this is to either:

    +
    +    if (stream)
    +        if (stream.can_print())
    +
    +

    or

    +
    +    if (!!stream && stream.can_print())
    +
    +

    This also affects logical operator ||.

    + +
    Rationale for Implementation
    + +

    Another possible implementation for bool_testable was the + safe-bool idiom as found in shared_ptr<> + . This implementation required the user to provide + operator!, and provided an + operator unspecified-bool-type() conversion in return. It had + the advantage of slight more descriptive diagnostic messages in the case of + syntax errors. But this implementation had issues when used with a class + with user defined integer conversion operators. For example:

    + +
    +class MyInt : alternative_bool_testable<MyInt>
    +{
    +public:
    +    bool operator!() const;
    +    operator int() const;
    +};
    +
    +void g(int);
    +
    +void f(const MyInt& i)
    +{
    +    if (!i) // fine: calls operator!
    +        ...
    +
    +    g(i);   // fine: calls operator int
    +
    +    if (i)  // error: calls operator int NOT operator unspecified-bool-type()
    +        ...
    +}
    +
    +

    Grouped Arithmetic Operators

    The following templates provide common groups of related operations. @@ -2062,6 +2191,12 @@

    Contributed the NRVO-friendly and symmetric implementation of arithmetic operators.
    + +
    Sam Partington
    + +
    Contributed the bool_testable class, assisted by Daniel Frey and + David Abrahams.
    +

    Note for Users of Older Versions