dag@control.lth.se (Dag Bruck) (05/30/91)
In article <1991May29.171209.14760@neon.Stanford.EDU> philip@pescadero.stanford.edu writes: >.... But how many programs would break? I for one would be prepared >to pay the price for the long-term gain, but I generally try to program >as if boolean and int are distinct types, so the price wouldn't be >very high for me. The "break old code" argument against any changes is the one you hear most often at the C++ standardization meetings. It is of course valid, but often over-used. Even if there were incompatible changes, every compiler would have a switch to get the old behaviour. One of the strongest arguments in favour of a new boolean data type is that you could do function overloading: void f(int); void f(boolean); I also think a boolean data type would increase type safety in C++, at least the way I program (:-). 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 think a boolean data type should _not_ be another kind of integer (at least eventually) which can be implicitly converted to/from int. It should instead be a unique enumerated type, but that doesn't work until all standard functions (e.g., operator == (int, int)) return a boolean and not an int. The transition to a better world (:-) should be done in two phases: 1. Introduce the new built-in data type `boolean' (or whatever you call it), and specify that all standard operator == (etc.) return a boolean. 2. Include implicit type conversions between boolean and int, to minimize the number of broken programs. I think this automatic conversion will help in most cases. 3. Warn about the automatic conversions and label them as anachronisms. 4. (Some years later) Turn the warnings of (3) into errors. We had a similar case with C++ 2.0 with respect to handling of `enum', and I think the transition was relatively painless. The most common problem was that people had used an enum for booleans, which caused warning messages under the new interpretation. Dag Br!"uck -- Department of Automatic Control E-mail: dag@control.lth.se Lund Institute of Technology P. O. Box 118 Phone: +46 46-104287 S-221 00 Lund, SWEDEN Fax: +46 46-138118
pena@brainware.fi (Olli-Matti Penttinen) (05/30/91)
In article <1991May30.060200.6590@lth.se> dag@control.lth.se (Dag Bruck) writes:
void f(int);
void f(boolean);
I also think a boolean data type would increase type safety in C++, at
least the way I program (:-).
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 think a boolean data
type should _not_ be another kind of integer (at least eventually) which
can be implicitly converted to/from int. It should instead be a
unique enumerated type, but that doesn't work until all standard
functions (e.g., operator == (int, int)) return a boolean and not
an int.
I partly agree. It would be nice, if operator==(T,T) would return a
truly boolean value. On the other hand, it is possible to achieve the
same type safety if one implements not only a class boolean, but
classes real, integer, string, and what not, as well. That would of
course introduce a rather severe performance penalty, however. If only
current compilers did a better job in optimizing common
sub-expressions involving inlined access member functions and such... :-(
I know of at least one project, in which the group (they used Ada)
redefined practically everything, and to some extent succeeded. They
did peculiar things like had an "enum boolean { true, false, i_dont_care,
i_dont_know}" type of a construct.
Summa summarum: once again we face a consept that could be
incorporated to the language and indeed would fit in well, but without
which we can manage. IMHO, that means we shouldn't have it.
Especially, since no current library can support it.
Dag Br!"uck
--
Department of Automatic Control E-mail: dag@control.lth.se
Lund Institute of Technology
P. O. Box 118 Phone: +46 46-104287
S-221 00 Lund, SWEDEN Fax: +46 46-138118
==pena
--
Olli-Matti Penttinen <pena@brainware.fi> | "When in doubt, use brute force."
Brainware Oy | --Ken Thompson
P.O.Box 330 +----------------------------------
02151 ESPOO, Finland Tel. +358 0 4354 2565 Fax. +358 0 461 617
tom@elan.Elan.COM (Thomas Smith) (05/31/91)
[ 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
npw@eleazar.dartmouth.edu (Nicholas Wilt) (06/02/91)
Defining your own Boolean type (with #defines, typedefs, or classes, as you prefer) has advantages, but they are far outweighed by the problems introduced when someone tries to use your code (or, conversely, when you're trying to deal with code full of Booleans of one flavor or another). What happens when you try to make use of two libraries, one of which thinks Boolean is a "typedef int" and another which thinks Boolean is a class? You could go through renaming and reworking, but that shouldn't be necessary. C++ inherits a pretty reasonable treatment of integers as Boolean values from C (nonzero is True when evaluating, Boolean expressions evaluate to integer 1 or 0). It's portable, reasonably clean and flexible--for instance, there's no other way to stuff multiple Booleans into a single word, like you can with the : construct in C structures. A little less pretty than any of the ten thousand other ways people can think of to deal with Boolean values, but unlike any of those, it's standard. Overall, I think the disadvantages outweigh the advantages. I hate buying C source code and seeing Boolean defined explicitly. It gets ripped out as soon as a need develops to interface with it more than perfunctorily. --Nick npw@eleazar.dartmouth.edu