home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.lang.c++
- Path: sparky!uunet!wupost!rice!news.rice.edu!dougm
- From: dougm@titan.cs.rice.edu (Doug Moore)
- Subject: New C++ type: boole
- Message-ID: <DOUGM.92Jul25234214@titan.cs.rice.edu>
- Sender: news@rice.edu (News)
- Organization: Rice University Computer Science, Houston, Texas
- Date: Sun, 26 Jul 1992 05:42:14 GMT
- Lines: 459
-
- >>>>> On 21 Jul 92 05:05:52 GMT, daveg@synaptics.com (Dave Gillespie) said:
- Dave> If you define "t!!" as a "t" token followed by two "!" tokens, using
- Dave> the existing C++ lexical rules, then you still have the same sort of
- Dave> problem: "if (t!!==2)" cannot be scanned properly (not left-to-right,
- Dave> anyway).
-
- Dave> If you define "t!!" as a single token, may the fleas of a thousand
- Dave> camels, well, you get the idea. :-)
-
- Dave> Let's do away with t!! and f!! altogether: The expressions !!1 and
- Dave> !!0 are just as simple, and we get them for free. I find them easier
- Dave> to tell apart at a glance, too.
-
- Although the needs of the writers of scanners was not my primary
- concern when I proposed t!! and f!!, I can agree that they might make
- their lives a little difficult, and might make everyone's scanners a
- little slower.
-
- On the other hand, I do want boole literals and not circumlocutions
- like !!0 and !!1. I could live with 0t and 0f, and I don't think the
- scanner writers would wish upon me an infestation of dromedary vermin
- for inventing those two particular symbols. Would they?
-
- Dave> Under "advantages," you might list the ability of a class to define
- Dave> "operator boole()" conversions instead of/as well as "operator int()".
- Dave> Many classes define misleading "int" conversions when they really
- Dave> want only a boolean conversion.
-
- Noted. Thank you.
-
- Dave> Is it possible for a template "Array<boole>" to define itself
- Dave> naturally as a packed bit vector? That would be pretty cool.
-
- Yeah, but I don't see how to do it.
-
- Dave> Does there need to be any mention of "signed", "unsigned", "short",
- Dave> and "long" as applied to "boole"? (Specifically, that all of these
- Dave> are disallowed?)
-
- Probably not, but I have added a note. Thanks.
-
- Dave> #ifndef __STDCPLUS__
- Dave> typedef int boole;
- Dave> // or: #define boole int
- Dave> #endif
-
- Dave> What can be done to ease the transition from current C++ to C++
- Dave> with booleans?
-
- Well, one could probably cook up a class boole that one could
- conditionally include if using an unenlightened compiler. That
- wouldn't solve everything. Anytime you add to the language, programs
- that use the new features can't be compiled with the old compilers. I
- can't see a global solution to that.
-
- Dougm> The behavior of an expression of the form E1 &&= E2 is equivalent to
- Dougm> E1 ? (E1=(E2)) : f!, except that E1 is evaluated only once.
-
- Dave> Any reason you wrote it that way instead of as "E1 = E1 && E2"? The
- Dave> only way I can see that this would make a difference is if "E1" is a
- Dave> volatile variable. Is that rare case worth sacrificing the elegance
- Dave> of defining "E1 <op>= E2" as "E1 = E1 <op> E2" always?
-
- I wrote it that way to emphasize that in E1 &&= E2 or E1 ||= E2, no
- assignment need take place if E1 has the appropriate value. That
- is probably sufficiently obvious to go unsaid.
-
- Dave> There is a minor typo in section 1 of your proposal:
- Bug noted and corrected. Thank you.
-
- Doug Moore
- (dougm@cs.rice.edu)
-
- P. S. The latest draft of the proposal follows. Constructive
- feedback is still welcome. Shall I officialize it and send it off to
- our beloved standards committee?
-
- Proposed extension to C++: A Boolean type
- Version 2: 26 Jul 1992
- Doug Moore
- dougm@cs.rice.edu
-
- 0. Introduction
-
- One of the weakness of the type system that C++ inherited from C is in
- the overuse of the int type. In particular, a Boolean type
- representing truth and falsehood does not exist in C, as it does in
- many languages, but instead truth and falsehood are represented by
- integral values 1 and 0.
-
- To some, the weakness of the type system is a strength of the
- language, and expressions like "8 + 5*(a<b)" are part of their
- programming idiom. No proposed change to C++ can invalidate such
- expressions. To many, however, the weakness of the type system that
- permits programming errors to go undetected is a language flaw. The
- language should provide greater type safety to those who want it.
- Thus, I propose the extension of C++ to define a boolean type. A
- complete list of amendments to the base document that support the
- extension appears at the end of this document.
-
- 1. Outline of the extension.
-
- I propose to add to C++ a new integral type, boole, and literals of
- that type, 0t, and 0f. Besides paying tribute to a pioneer in the
- formalization of logic, the type name is not one that has been popular
- with those who have tried to simulate boolean types in the past.
- Therefore, that choice of type name is less likely to break current
- code than a type name like "bool" or "Boolean". The literal names 0t
- and 0f cannot appear, even accidentally, in current code.
-
- The boole type is generated as the result of comparison operations, as
- the result of applying the logical connectives && and ||, and as the
- result of applying the unary operator ! to boole, pointer and
- arithmetic types. It is used in the first-expression parts of
- conditional expressions (?:), and as the test expressions in if, for,
- while and do statements. When arithmetic or pointer types appear in a
- context that requires a boolean value, standard logical conversions
- are applied to convert nonzero arithmetic and nonnull pointer types to
- 0t. Warnings can be generated when logical conversions are applied;
- such warnings should be optional early compilers, and later compilers
- should warn by default but optionally disable warnings.
-
- The boole type is an integral type, and in a general arithmetic
- context can be promoted to an integer value 0 or 1. Integral
- promotion of boole values generates warnings, optionally at first, but
- eventually by default.
-
- 2. New and redefined operators.
-
- Certain operators can be usefully reinterpreted when boole values are
- distinguished from other integral values. In particular, the unary
- operator ! can be read as isFalse (when applied to booles), as isZero
- (when applied to arithmetic values) and as isNull (when applied to
- pointers). This proposal does not, therefore, require that warnings
- be issued when ! is applied to various types. It is hoped that by
- distinguishing the three different meanings of !, confusion about null
- pointers and their representation may be lessened.
-
- The ++ and -- operators serve a useful, if redundant, purpose in the
- extension. When applied to boole lvalues, they each invert the
- lvalue. Thus "b[<expr>] = !b[<expr>]" or, more likely, "b[<expr>] ^=
- 1" could be replaced by "++b[<expr>]". Note that the use of ++ to
- toggle logical values is already a common idiom, particularly in the
- decoding of command line options and the corresponding setting of
- flags.
-
- New operators &&= and ||= extend the op= paradigm, in that they permit
- replacement of, for example, (b1 = b1 && b2) by (b1 &&= b2). Such
- operators could prove especially useful in a context like (b1[<expr>]
- && = b2), particularly if <expr> has side effects. The expression
- could not otherwise be written without the introduction of a temporary
- variable. Like their underlying logical connectives, these assignment
- operators are short-circuiting; that is, the right hand side need not
- be evaluated if the left hand side determines the result of the
- operation.
-
- 3. Additional advantages to the extension.
-
- Among the common errors that will generate warnings when the extension
- is adopted are the confusion of assignment and equality testing (if (a
- = b)) and the confusion that can arise in interval testing (if (a < b
- < c)). In general, the inadvertant mixture of arithmetic and boolean
- values will be detected and corresponding bugs avoided.
-
- Functions will be overloadable on boolean values, which will be
- convenient for some class designers. Conversion operators "operator
- boole()", "operator void*()", and "operator int()" will be able to
- simultaneously coexist, which again may convenience some class
- designers.
-
- The primary advantage is probably the resulting elimination of
- progammer defined, conflicting boolean types. That so many
- programmers choose to simulate a boolean type suggests that it would
- be a popular language feature. That so many programmers do it
- differently suggests that there is not a clearcut way to do it well
- within the limits of the current language.
-
- 4. Disadvantages to the extension.
-
- Programmers who now deliberately overload a function to take an int
- argument, and then call that function with an argument that is of
- boole type under this proposal, will have their programs break. They
- will have to cast the result argument to int explicitly.
-
- Programs that use the identifier "boole" will break.
-
- The warnings issued for integral promotions of booles and logical
- conversion of arithmetic and pointer types may annoy some. The
- warnings can be eliminated by explicit casts or, better, by replacing
- <boolexpr> by (<boolexpr>?1:0) and <arithexpr> by !!(<arithexpr>)
- where appropriate.
-
- 5. Questions about the extension.
-
- Q. What is the size of the boole type? I suspect that it would
- probably be best to define it to have an implementation defined size
- so an implementation can choose to pack an array of boole as a bit
- vector.
-
- A. The size of the boole type is one. An implementation cannot
- automatically pack booles, since doing so would make it impossible to
- have a type boole* (pointer to boole), an array of booles, etc.
-
- 6. Conclusions.
-
- The changes proposed here will not break existing programs, except in
- rare cases. They will help standardize a practice of many programmers
- and library writers. There is ample experience with similar types in
- many other languages, including Fortran and Pascal, to suggest that
- the technical obstacles to supporting such a type are minimal.
-
- 7. Amendments to base document.
-
- ======================================================================
- In 2.4 (Keywords), add "boole" to the list of keyword identifiers.
- Add "&&=" and "||=" to the list of "character combinations (...) used
- as operators."
-
- ======================================================================
- In 2.5 (Literals), add "boolean-constant" to the beginning of the list
- of literals.
-
- ======================================================================
- Add a new subsection before 2.5.1 (Integer Constants), to read:
- <begin quote>
-
- A boolean constant consists of '0' followed by one of 't' or 'f'. The
- constant 0t denotes truth. The constant 0f denotes falsehood.
-
- <end quote>
-
- ======================================================================
- In 3.6.1 (Fundamental Types), add the following after the first
- paragraph:
- <begin quote>
-
- A boolean type, declared boole, is available. Booleans provide the
- smallest addressable quantity of storage. The value of a boolean is
- equivalent to 1 for 0t and 0 for 0f.
-
- <note> Booles may not be declared signed or unsigned, long or short.
-
- <end quote>
-
- Change the penultimate paragraph to:
- <begin quote>
-
- Types boole, char, int of all sizes, and enumerations (7.2) are
- collectively called integral types. Integral and floating types are
- collectively called arithmetic types.
-
- <end quote>
-
- ======================================================================
- In 4.1 (Integral Promotions), change the first paragraph to begin:
- <begin quote>
-
- A boole, a char, a short int, ....
-
- <end quote>
-
- <Note: Compilers can detect and warn against the use of implicit
- promotions of boole to int.>
-
- ======================================================================
- Add a new section after 4.5 (Arithmetic Conversions) as follows:
-
- <begin quote>
-
- 4.x Logical Conversions
-
- In many contexts, an expression having pointer type or non-boolean
- arithmetic type will appear where a value of boolean type is expected.
- In these circumstances, a value of pointer type is converted to the
- boolean value 0f if and only if the pointer value is that of the null
- pointer. A value of arithmetic type is converted to the boolean value
- 0f if and only if the value is zero.
-
- <Note: Compilers can detect and warn against the use of implicit
- conversions of arithmetic and pointer types to boole.>
-
- ======================================================================
- In 5.2.5 (Increment and Decrement), replace the fourth sentence of the
- first paragraph by:
- <begin quote>
-
- After the result is noted, the object is incremented by 1, if
- non-boolean, or inverted, if boolean.
-
- <end quote>
-
- ======================================================================
- In 5.3 (Unary operators), replace the penultimate paragraph by:
- <begin quote>
-
- The operand of the operator ! must have arithmetic, pointer, or
- boolean type. For arithmetic types, its value is 0t if its operand
- is zero, 0f otherwise. For pointer types, its value is 0t if its
- operand is the null pointer, 0f otherwise. For boolean types, its
- value is the logical negation of its operand.
-
- <end quote>
-
- ======================================================================
- In 5.3.1 (Increment and Decrement), replace the first sentence of the
- first paragraph by:
- <begin quote>
-
- The operand of prefix ++ is incremented by 1 if arithmetic, or
- inverted if boolean.
-
- <end quote>
-
- ======================================================================
- In 5.9 (Relational Operators), change the second paragraph to:
- <begin quote>
-
- The operands must have arithmetic or pointer type. The operators <
- (less than), > (greater than), <= (less than or equal to), and >=
- (greater than or equal to) all yield 0f if the specified relation is
- false and 0t if it is true. The type of the result is boole.
-
- <end quote>
-
- ======================================================================
- In 5.10 (Equality Operators), change the second sentence of the first
- paragraph to:
-
- <begin quote>
-
- (Thus a<b == c<d is 0t whenever a<b and c<d have the same truth-value.)
-
- <end quote>
-
- ======================================================================
- In 5.14 (Logical AND Operator), replace the two paragraphs by:
-
- <begin quote>
-
- The && operator groups left-to-right. It returns 0t if both its
- operands are 0t, 0f otherwise. Unlike &, && guarantees left-to-right
- evaluation; moreover the second operand is not evaluated if the first
- operand evaluates to 0f.
-
- The operands each have boolean type. The result is a boole. All side
- effects of the first expression happen before the second expression is
- evaluated.
-
- <end quote>
-
- <Note: Logical conversion (4.x) permits any arithmetic or pointer type
- to appear as an operand, to be converted to boolean type.>
-
- ======================================================================
- In 5.15 (Logical OR Operator), replace the two paragraphs by:
-
- <begin quote>
-
- The || operator groups left-to-right. It returns 0t if either of its
- operands are 0t, 0f otherwise. Unlike |, || guarantees left-to-right
- evaluation; moreover the second operand is not evaluated if the first
- operand evaluates to 0t.
-
- The operands each have boolean type. The result is a boole. All side
- effects of the first expression happen before the second expression is
- evaluated.
-
- <end quote>
-
- <Note: Logical conversion (4.x) permits any arithmetic or pointer type
- to appear as an operand, to be converted to boolean type.>
-
- ======================================================================
- In 5.16 (Conditional Operator), replace the first paragraph by:
-
- <begin quote>
-
- Conditional expressions group right-to-left. The first expression
- must have boolean type. It is evaluated and if it is false, the
- result of the conditional expression is the value of the second
- expression, otherwise that of the third expression. All side effects
- of the first expression happen before the second or third expression
- is evaluated.
-
- <end quote>
-
- <Note: Logical conversion (4.x) permits any arithmetic or pointer type
- to appear as the first operand, to be converted to boolean type.>
-
- ======================================================================
- In 5.17 (Assignment Operators), add to the list of assignment
- operators "&&=" and "||=".
-
- ======================================================================
- In 6.4.1 (The if Statement), change the first two paragraphs to:
- <begin quote>
-
- The expression must be of boolean type or of a class type for which an
- unambiguous conversion to boolean type exists (12.3).
-
- The expression is evaluated and if it is true, the first substatement
- is executed. If else is used, the second substatement is executed if
- the expression is false. The else ambiguity is resolved by connecting
- an else with the last encountered else-less if.
-
- <end quote>
-
- <Note: Logical conversion (4.x) permits any arithmetic or pointer type
- to appear as the expression, to be converted to boolean type.>
-
- ======================================================================
- In 6.5.1 (The while Statement), change the first two paragraphs to:
- <begin quote>
-
- In the while statement the substatement is executed repeatedly until
- the value of the expression becomes false. The test takes place
- before each executeion of the statement.
-
- The expression must be of boolean type or of a class type for which an
- unambiguous conversion to boolean type exists (12.3).
-
- <end quote>
-
- <Note: Logical conversion (4.x) permits any arithmetic or pointer type
- to appear as the expression, to be converted to boolean type.>
-
- ======================================================================
- In 6.5.2 (Do statement), change the first two paragraphs to:
- <begin quote>
-
- In the do statement the substatement is executed repeatedly until
- the value of the expression becomes false. The test takes place
- after each executeion of the statement.
-
- The expression must be of boolean type or of a class type for which an
- unambiguous conversion to boolean type exists (12.3).
-
- <end quote>
-
- <Note: Logical conversion (4.x) permits any arithmetic or pointer type
- to appear as the expression, to be converted to boolean type.>
-
- ======================================================================
- In 6.5.3 (The for Statement), change "zero" to "false" in the first
- paragraph. Change the last sentence of the first paragraph to:
- <begin quote>
-
- The first expression must be of boolean type or of a class type for
- which an unambiguous conversion to boolean type exists (12.3).
-
- <end quote>
-
- Change the second sentence, second paragraph to:
- <begin quote>
-
- A missing expression-1 makes the implied while clause equivalent to
- while(0t).
-
- <end quote>
-