c++boostsafe-bool-idiom

Safe bool idiom in boost?


Does the boost library provide an implementation of a safe bool idiom, so that I could derive my class from it?

If yes - where is it?

If no - what are my alternatives beyond implementing it myself?


I found the following similar question: " Is there a safe bool idiom helper in boost? " and the accepted answer suggests using bool_testable<> in Boost.Operators.

Unfortunately, when I checked the boost manual I couldn't find it there. Code using it fails to compile too.

I also stumbled on another SO question " Was boost::bool_testable<> relocated or removed? " and the comment there suggests that the bool_testable actually never made to any release version of the boost.

There is also an interesting article by Bjorn Karlsson on the subject which contains a code which could be copy-pasted into my project. I am hoping however, that there is a commonly accepted and maintained utility library (e.g. boost) that implements that already.


For compatibility reasons, I do not want to rely on C++11.


Solution

  • I do not know of a commonly accepted utility library that provides the safe-bool idiom. There have been a few attempts within Boost, and they often result in debates about how to provide a safe-bool implementation (naming conventions, macros, inline includes, inheritance). As a result, there are at least three implementations existing within Boost, with only one of the implementations, Boost.Spirit.Classic's safe_bool, designed for external use.


    Details and concepts for each implementation:


    This example uses Boost 1.50. Each class should evaluate to true in boolean context if the integer passed to the constructor is greater than 0:

    // Safe-bool idiom with Boost.Range.
    #include <boost/range/detail/safe_bool.hpp>
    class range_bool
    {
    public:
      range_bool( int x ) : x_( x ) {}
    private:
      // None of these are required, but makes the implementation cleaner.
      typedef boost::range_detail::safe_bool< int range_bool::* > safe_bool_t;
      typedef safe_bool_t::unspecified_bool_type unspecified_bool_type;
      int dummy;
    public:
      operator unspecified_bool_type() const
      {
        return safe_bool_t::to_unspecified_bool( x_ > 0, &range_bool::dummy );
      }
    private:
      int x_;
    };
    
    // Safe-bool idiom with Boost.SmartPtr.
    #include <boost/detail/workaround.hpp>
    class smart_ptr_bool
    {
    public:
      smart_ptr_bool( int x ) { px = ( x > 0 ) ? &dummy : 0 ; }
    private:
      typedef smart_ptr_bool this_type; // -.
      typedef int T;                    //   :- Required concepts when using
      T* px;                            // -'   smart_ptr's operator_bool.
    private:
      T dummy; // Simple helper.
    public:
      #include <boost/smart_ptr/detail/operator_bool.hpp>
    };
    
    // Safe-bool idiom with Boost.Spirit.
    #include <boost/spirit/include/classic_safe_bool.hpp>
    class spirit_bool: public boost::spirit::classic::safe_bool< spirit_bool >
    {
    public:
      spirit_bool( int x ) : x_( x ) {} 
    public:
      // bool operator_bool() is required by the spirit's safe_bool CRTP.
      bool operator_bool() const { return x_ > 0; }
    private:
      int x_;
    };
    
    #include <iostream>
    
    int main()
    {
      std::cout << "range_bool( -1 ):     " << range_bool( -1 )     << std::endl
                << "range_bool(  1 ):     " << range_bool(  1 )     << std::endl
                << "smart_ptr_bool( -1 ): " << smart_ptr_bool( -1 ) << std::endl
                << "smart_ptr_bool(  1 ): " << smart_ptr_bool(  1 ) << std::endl
                << "spirit_bool( -1 ):    " << spirit_bool( -1 )    << std::endl
                << "spirit_bool(  1 ):    " << spirit_bool(  1 )    << std::endl;
      return 0;
    }
    

    Resulting output:

    range_bool( -1 ):     0
    range_bool(  1 ):     1
    smart_ptr_bool( -1 ): 0
    smart_ptr_bool(  1 ): 1
    spirit_bool( -1 ):    0
    spirit_bool(  1 ):    1

    I do not know of any alternatives. When I have ran across safe-bool idioms, most of the implementations have been a copy-and-paste variants of the implementation provided in Bjorn Karlsson's article.