TITLE: why bool - a rationale AUTHOR: Herb Sutter (herbs@cntc.com) Guru of the Week #26: bool (Difficulty: 7 / 10) Problem Besides wchar_t (which was a typedef in C), bool is the only builtin type to be added to C++ since the ARM.[1] Could bool's effect have been duplicated without adding a builtin type? If yes, show an equivalent implementation. If no, show why possible implementations do not behave the same as the builtin bool. [1] Ellis M. and Stroustrup B., "The Annotated C++ Reference Manual" (Addison-Wesley, 1990). Solution The answer is: No. The bool builtin type (and the reserved keywords true and false) were added to C++ precisely because they couldn't be duplicated completely using the existing language. There are four major implementations: Option 1: Typedef (score: 8.5 / 10) ----------------- This option means to "typedef bool;", typically: typedef int bool; const bool true = 1; const bool false = 0; This solution isn't bad, but it doesn't allow overloading on bool. For example: // file f.h void f( int ); // ok void f( bool ); // ok, redeclares the same function // file f.cpp void f( int ) { /*...*/ } // ok void f( bool ) { /*...*/ } // error, redefinition So Option #1 isn't good enough. Option 2: #define (score: 0 / 10) ----------------- This option means to "#define bool ", typically: #define int bool #define true 1 #define false 0 This is, of course, purely evil. Not only doesn't it allow overloading, either, but it wreaks the usual havoc of #defines. For example, pity the poor customer who tries to use this library and already has a variable named 'false'; now this definitely behaves differently from a builtin type. Trying to use the preprocessor to simulate a type is just a bad idea. Option 3: Enum (score: 9 / 10) -------------- This option means to make an "enum bool", typically: enum bool { false, true }; This is somewhat better than Option 1, in my opinion. It allows overloading (the main problem with #1), but doesn't allow automatic conversions from a conditional expression (which would have been possible with #1), to wit: bool b; b = ( i == j ); This doesn't work because ints cannot be implicitly converted to enums. Option 4: Class (score: 9 / 10) --------------- Heck, this is an object-oriented language, right? So why not write an class, typically: class bool { public: bool(); bool( const bool& ); operator=( const bool& ); bool( int ); // to enable conversions from operator=( int ); // conditional expressions //operator int(); // questionable! //operator void*(); // questionable! private: unsigned char b_; }; const bool true ( 1 ); const bool false( 0 ); This works except for the conversion operators marked "questionable". They're questionable because: 1. Without a conversion to something like int or void*, bool objects can't be tested "naturally" in conditions. For example: bool b; /*...*/ if( b ) // error without an automatic conversion to { // something like int or void* /*...*/ } 2. With an automatic conversion, bools will interfere with overload resolution, just as do all classes having non-explicit (conversion) constructors and/or automatic conversions (especially conversions from/to common types). It's a classic Catch-22 situation: We must choose one or the other, but neither option lets us duplicate the effect of having a builtin bool type. Summary ------- A typedef ... bool wouldn't allow overloading on bool. A #define bool wouldn't allow overloading either and would wreak the usual havoc of #defines. An enum bool would allow overloading but couldn't be automatically converted from a conditional expression (as in "b = (i == j);"). A class bool would allow overloading but wouldn't let a bool object be tested in conditions (as in "if( b )") unless it provided an automatic conversion to something like int or void*, which would wreak the usual havoc of automatic conversions. Yes, we really did need a builtin bool! [1] Ellis M. and Stroustrup B., "The Annotated C++ Reference Manual" (Addison-Wesley, 1990).