Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C++

Reusable safe_bool Implementation

5.00/5 (4 votes)
12 Jan 2010CPOL 16.6K  
Reusable safe_bool implementation
safe_bool - what & why[^]?

In my understanding their implementation is broken (if fixable), but in the course I came up with my own that appears slightly more elegant to me:

C++
template <typename T>
class safe_bool 
{
protected:
   typedef void (safe_bool::*bool_type)() const;
   bool_type to_bool_type(bool b) const 
    { return b ? &safe_bool<T>::safe_bool_true : 0; }
 
private:
   void safe_bool_true() const {}
   bool operator ==(safe_bool<T> const & rhs); 
   bool operator !=(safe_bool<T> const & rhs); 
};

Can be used like this:

C++
struct A : public safe_bool<A>
{
   operator bool_type() const { return to_bool_type(true); }
   // replaces:
   // operator bool() const { return true; }
};

From all samples I found that's the cleanest to write and read, while only the two symbols bool_type and to_bool_type "escape" to derived classes.

I am putting this up for review, since I'm clearly at the limits of my understanding of the standard. However, the following test cases pass on VC 2008:

C++
struct A : public safe_bool<A>
{
   operator bool_type() const { return to_bool_type(true); }
};
 
struct B : protected safe_bool<B> // protected is ok, too
{
   operator bool_type() const { return to_bool_type(false); }
};
 
struct C : public B
{
   operator bool_type() const { return to_bool_type(rand() < RAND_MAX / 2); }
}; 

void SafeBootCompileFails()
{
   A a, a2;
   B b;
   C c;
 
   if (a) {}      // Yes!
   if (!a) {}     // Yes!

   a=a;           // Yes! (default assignment op should be allowed)
   a=a2;          // Yes! (default assignment op should be allowed)

   long l = a;    // No!

   if (a==a2) {}  // No!
   if (a!=a2) {}  // No!
   if (a<a2)  {}  // No!

   if (a==b) {}   // No!
   if (a!=b) {}   // No!
   if (a<b)  {}   // No!
   
   if (b==c) {}   // No!
   if (b!=c) {}   // No!
   if (b<c)  {}   // No!

   a=b;           // No!

   b = c;         // Yes, slicing. Not my problem today.
}

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)