Xref: utzoo comp.lang.c++:13791 comp.std.c++:946 Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!zaphod.mps.ohio-state.edu!swrinde!cs.utexas.edu!sun-barr!ames!elan!tom From: tom@elan.Elan.COM (Thomas Smith) Newsgroups: comp.lang.c++,comp.std.c++ Subject: Re: Boolean confusion (class implementation) Message-ID: <998@elan.Elan.COM> Date: 30 May 91 21:34:41 GMT References: <1991May30.060200.6590@lth.se> Followup-To: comp.lang.c++ Distribution: comp.lang.c++ Organization: Elan Computer Group, Inc., Mountain View, CA Lines: 71 [ Continuing thread about merits/pitfalls of defining a boolean type in your application, and colliding with definitions in other modules. ] From article <1991May30.060200.6590@lth.se>, by dag@control.lth.se (Dag Bruck): > I once tried to implement `class boolean' and failed. Firstly there > was a performance problem, which I think good compilers could > overcome. Secondly, I don't think I gained anything in type safety > and little in convenience: to be at all useful I needed implicit type > conversions int->boolean and boolean->int. I have successfully implemented Boolean data types in several large projects (100K+ lines of C++) at the last two companies I have worked for. If you set it up right, you do get the type-safety without the performance penalty. In most cases, the biggest concern was size - could we get a Boolean class that would have size == 1 byte (the minimum) and align on single-byte boundaries when packed in structures. The answer is... depends on the architecture. Here is what I usually end up with: class Boolean { unsigned char value; friend int operator== (Boolean left, Boolean right); friend int operator!= (Boolean left, Boolean right); public: Boolean() {} Boolean(int i) { value = ((i) ? 1 : 0); } operator int() const { return (int) value; } }; inline int operator== (Boolean left, Boolean right) { return left.value == right.value; } inline int operator!= (Boolean left, Boolean right) { return left.value != right.value; } // defined in the source file as initialized to 0 and 1, respectively extern const Boolean FALSE; extern const Boolean TRUE; Notice that initialization by int is allowed (via constructor), but assignment is not (no operator=(int)). There are some pitfalls with this approach, however: 1) The type name Boolean sometimes collides with "helpful" libraries that *just know* you will need a type called Boolean that is a typedef'd unsigned char. The X toolkit (Xt) is a prime offender. Folks, what's the point of sticking the Xt prefix on 95% of the types defined, and skipping the 5% most likely to collide with an application's own types? This can be worked around by simply calling your Boolean something else, like TBoolean (Tom's Boolean :^), and undefining TRUE and FALSE at the beginning of the header file (if they were defines and not an enum). 2) The constant values TRUE and FALSE are globals that are initialized via constructor, and thus cannot be safely used in other global constructors. Buckle up for safety... All in all, though, the good outweighs the bad. One other reason that I usually settle on the class approach for Boolean types is that I often need many other similar types - for instance Status (SUCCESS or FAILURE) - which are not compatible with Boolean and can cause trouble if they are assigned to each other. (Of course, Status is defined as int by the X11 Xlib.h header file - don't get me started on graduate-student software again). Hope this was somewhat helpful - I feel better now. Thomas Smith Elan Computer Group, Inc. (415) 964-2200 tom@elan.com, ...!{ames, uunet, hplabs}!elan!tom