home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #16 / NN_1992_16.iso / spool / comp / lang / cplus / 11557 < prev    next >
Encoding:
Text File  |  1992-07-25  |  18.3 KB  |  470 lines

  1. Newsgroups: comp.lang.c++
  2. Path: sparky!uunet!wupost!rice!news.rice.edu!dougm
  3. From: dougm@titan.cs.rice.edu (Doug Moore)
  4. Subject: New C++ type: boole
  5. Message-ID: <DOUGM.92Jul25234214@titan.cs.rice.edu>
  6. Sender: news@rice.edu (News)
  7. Organization: Rice University Computer Science, Houston, Texas
  8. Date: Sun, 26 Jul 1992 05:42:14 GMT
  9. Lines: 459
  10.  
  11. >>>>> On 21 Jul 92 05:05:52 GMT, daveg@synaptics.com (Dave Gillespie) said:
  12.   Dave> If you define "t!!" as a "t" token followed by two "!" tokens, using
  13.   Dave> the existing C++ lexical rules, then you still have the same sort of
  14.   Dave> problem:  "if (t!!==2)" cannot be scanned properly (not left-to-right,
  15.   Dave> anyway).
  16.   
  17.   Dave> If you define "t!!" as a single token, may the fleas of a thousand
  18.   Dave> camels, well, you get the idea.  :-)
  19.   
  20.   Dave> Let's do away with t!! and f!! altogether:  The expressions !!1 and
  21.   Dave> !!0 are just as simple, and we get them for free.  I find them easier
  22.   Dave> to tell apart at a glance, too.
  23.  
  24. Although the needs of the writers of scanners was not my primary
  25. concern when I proposed t!! and f!!, I can agree that they might make
  26. their lives a little difficult, and might make everyone's scanners a
  27. little slower.
  28.  
  29. On the other hand, I do want boole literals and not circumlocutions
  30. like !!0 and !!1.  I could live with 0t and 0f, and I don't think the
  31. scanner writers would wish upon me an infestation of dromedary vermin
  32. for inventing those two particular symbols.  Would they?
  33.  
  34.   Dave> Under "advantages," you might list the ability of a class to define
  35.   Dave> "operator boole()" conversions instead of/as well as "operator int()".
  36.   Dave> Many classes define misleading "int" conversions when they really
  37.   Dave> want only a boolean conversion.
  38.  
  39. Noted.  Thank you.
  40.  
  41.   Dave> Is it possible for a template "Array<boole>" to define itself
  42.   Dave> naturally as a packed bit vector?  That would be pretty cool.
  43.  
  44. Yeah, but I don't see how to do it.
  45.  
  46.   Dave> Does there need to be any mention of "signed", "unsigned", "short",
  47.   Dave> and "long" as applied to "boole"?  (Specifically, that all of these
  48.   Dave> are disallowed?)
  49.  
  50. Probably not, but I have added a note.  Thanks.
  51.  
  52.   Dave> #ifndef __STDCPLUS__
  53.   Dave> typedef int boole;
  54.   Dave> // or: #define boole int
  55.   Dave> #endif
  56.   
  57.   Dave> What can be done to ease the transition from current C++ to C++
  58.   Dave> with booleans?
  59.  
  60. Well, one could probably cook up a class boole that one could
  61. conditionally include if using an unenlightened compiler.  That
  62. wouldn't solve everything.  Anytime you add to the language, programs
  63. that use the new features can't be compiled with the old compilers.  I
  64. can't see a global solution to that.
  65.  
  66.   Dougm> The behavior of an expression of the form E1 &&= E2 is equivalent to
  67.   Dougm> E1 ? (E1=(E2)) : f!, except that E1 is evaluated only once.
  68.  
  69.   Dave> Any reason you wrote it that way instead of as "E1 = E1 && E2"?  The
  70.   Dave> only way I can see that this would make a difference is if "E1" is a
  71.   Dave> volatile variable.  Is that rare case worth sacrificing the elegance
  72.   Dave> of defining "E1 <op>= E2" as "E1 = E1 <op> E2" always?
  73.  
  74. I wrote it that way to emphasize that in E1 &&= E2 or E1 ||= E2, no
  75. assignment need take place if E1 has the appropriate value.  That
  76. is probably sufficiently obvious to go unsaid.
  77.  
  78.   Dave> There is a minor typo in section 1 of your proposal:
  79. Bug noted and corrected.  Thank you.
  80.  
  81. Doug Moore
  82. (dougm@cs.rice.edu)
  83.  
  84. P. S.  The latest draft of the proposal follows.  Constructive
  85. feedback is still welcome.  Shall I officialize it and send it off to
  86. our beloved standards committee?
  87.  
  88. Proposed extension to C++: A Boolean type
  89. Version 2: 26 Jul 1992
  90. Doug Moore
  91. dougm@cs.rice.edu
  92.  
  93. 0. Introduction
  94.  
  95. One of the weakness of the type system that C++ inherited from C is in
  96. the overuse of the int type.  In particular, a Boolean type
  97. representing truth and falsehood does not exist in C, as it does in
  98. many languages, but instead truth and falsehood are represented by
  99. integral values 1 and 0.
  100.  
  101. To some, the weakness of the type system is a strength of the
  102. language, and expressions like "8 + 5*(a<b)" are part of their
  103. programming idiom.  No proposed change to C++ can invalidate such
  104. expressions.  To many, however, the weakness of the type system that
  105. permits programming errors to go undetected is a language flaw.  The
  106. language should provide greater type safety to those who want it.
  107. Thus, I propose the extension of C++ to define a boolean type.  A
  108. complete list of amendments to the base document that support the
  109. extension appears at the end of this document.
  110.  
  111. 1. Outline of the extension.
  112.  
  113. I propose to add to C++ a new integral type, boole, and literals of
  114. that type, 0t, and 0f.  Besides paying tribute to a pioneer in the
  115. formalization of logic, the type name is not one that has been popular
  116. with those who have tried to simulate boolean types in the past.
  117. Therefore, that choice of type name is less likely to break current
  118. code than a type name like "bool" or "Boolean".  The literal names 0t
  119. and 0f cannot appear, even accidentally, in current code.
  120.  
  121. The boole type is generated as the result of comparison operations, as
  122. the result of applying the logical connectives && and ||, and as the
  123. result of applying the unary operator ! to boole, pointer and
  124. arithmetic types.  It is used in the first-expression parts of
  125. conditional expressions (?:), and as the test expressions in if, for,
  126. while and do statements.  When arithmetic or pointer types appear in a
  127. context that requires a boolean value, standard logical conversions
  128. are applied to convert nonzero arithmetic and nonnull pointer types to
  129. 0t.  Warnings can be generated when logical conversions are applied;
  130. such warnings should be optional early compilers, and later compilers
  131. should warn by default but optionally disable warnings.
  132.  
  133. The boole type is an integral type, and in a general arithmetic
  134. context can be promoted to an integer value 0 or 1.  Integral
  135. promotion of boole values generates warnings, optionally at first, but
  136. eventually by default.
  137.  
  138. 2.  New and redefined operators.
  139.  
  140. Certain operators can be usefully reinterpreted when boole values are
  141. distinguished from other integral values.  In particular, the unary
  142. operator ! can be read as isFalse (when applied to booles), as isZero
  143. (when applied to arithmetic values) and as isNull (when applied to
  144. pointers).  This proposal does not, therefore, require that warnings
  145. be issued when ! is applied to various types.  It is hoped that by
  146. distinguishing the three different meanings of !, confusion about null
  147. pointers and their representation may be lessened.
  148.  
  149. The ++ and -- operators serve a useful, if redundant, purpose in the
  150. extension.  When applied to boole lvalues, they each invert the
  151. lvalue.  Thus "b[<expr>] = !b[<expr>]" or, more likely, "b[<expr>] ^=
  152. 1" could be replaced by "++b[<expr>]".  Note that the use of ++ to
  153. toggle logical values is already a common idiom, particularly in the
  154. decoding of command line options and the corresponding setting of
  155. flags.
  156.  
  157. New operators &&= and ||= extend the op= paradigm, in that they permit
  158. replacement of, for example, (b1 = b1 && b2) by (b1 &&= b2).  Such
  159. operators could prove especially useful in a context like (b1[<expr>]
  160. && = b2), particularly if <expr> has side effects.  The expression
  161. could not otherwise be written without the introduction of a temporary
  162. variable.  Like their underlying logical connectives, these assignment
  163. operators are short-circuiting; that is, the right hand side need not
  164. be evaluated if the left hand side determines the result of the
  165. operation.
  166.  
  167. 3. Additional advantages to the extension.
  168.  
  169. Among the common errors that will generate warnings when the extension
  170. is adopted are the confusion of assignment and equality testing (if (a
  171. = b)) and the confusion that can arise in interval testing (if (a < b
  172. < c)).  In general, the inadvertant mixture of arithmetic and boolean
  173. values will be detected and corresponding bugs avoided.
  174.  
  175. Functions will be overloadable on boolean values, which will be
  176. convenient for some class designers.  Conversion operators "operator
  177. boole()", "operator void*()", and "operator int()" will be able to
  178. simultaneously coexist, which again may convenience some class
  179. designers.
  180.  
  181. The primary advantage is probably the resulting elimination of
  182. progammer defined, conflicting boolean types.  That so many
  183. programmers choose to simulate a boolean type suggests that it would
  184. be a popular language feature.  That so many programmers do it
  185. differently suggests that there is not a clearcut way to do it well
  186. within the limits of the current language.
  187.  
  188. 4. Disadvantages to the extension.
  189.  
  190. Programmers who now deliberately overload a function to take an int
  191. argument, and then call that function with an argument that is of
  192. boole type under this proposal, will have their programs break.  They
  193. will have to cast the result argument to int explicitly.
  194.  
  195. Programs that use the identifier "boole" will break.
  196.  
  197. The warnings issued for integral promotions of booles and logical
  198. conversion of arithmetic and pointer types may annoy some.  The
  199. warnings can be eliminated by explicit casts or, better, by replacing
  200. <boolexpr> by (<boolexpr>?1:0) and <arithexpr> by !!(<arithexpr>)
  201. where appropriate.
  202.  
  203. 5. Questions about the extension.
  204.  
  205. Q. What is the size of the boole type? I suspect that it would
  206. probably be best to define it to have an implementation defined size
  207. so an implementation can choose to pack an array of boole as a bit
  208. vector.
  209.  
  210. A. The size of the boole type is one.  An implementation cannot
  211. automatically pack booles, since doing so would make it impossible to
  212. have a type boole* (pointer to boole), an array of booles, etc.
  213.  
  214. 6. Conclusions.
  215.  
  216. The changes proposed here will not break existing programs, except in
  217. rare cases.  They will help standardize a practice of many programmers
  218. and library writers.  There is ample experience with similar types in
  219. many other languages, including Fortran and Pascal, to suggest that
  220. the technical obstacles to supporting such a type are minimal.
  221.  
  222. 7. Amendments to base document.
  223.  
  224. ======================================================================
  225. In 2.4 (Keywords), add "boole" to the list of keyword identifiers.
  226. Add "&&=" and "||=" to the list of "character combinations (...) used
  227. as operators."
  228.  
  229. ======================================================================
  230. In 2.5 (Literals), add "boolean-constant" to the beginning of the list
  231. of literals.
  232.  
  233. ======================================================================
  234. Add a new subsection before 2.5.1 (Integer Constants), to read:
  235. <begin quote>
  236.  
  237. A boolean constant consists of '0' followed by one of 't' or 'f'.  The
  238. constant 0t denotes truth.  The constant 0f denotes falsehood.
  239.  
  240. <end quote>
  241.  
  242. ======================================================================
  243. In 3.6.1 (Fundamental Types), add the following after the first
  244. paragraph:
  245. <begin quote>
  246.  
  247. A boolean type, declared boole, is available.  Booleans provide the
  248. smallest addressable quantity of storage.  The value of a boolean is
  249. equivalent to 1 for 0t and 0 for 0f.
  250.  
  251. <note> Booles may not be declared signed or unsigned, long or short.
  252.  
  253. <end quote>
  254.  
  255. Change the penultimate paragraph to:
  256. <begin quote>
  257.  
  258. Types boole, char, int of all sizes, and enumerations (7.2) are
  259. collectively called integral types.  Integral and floating types are
  260. collectively called arithmetic types.
  261.  
  262. <end quote>
  263.  
  264. ======================================================================
  265. In 4.1 (Integral Promotions), change the first paragraph to begin:
  266. <begin quote>
  267.  
  268. A boole, a char, a short int, ....
  269.  
  270. <end quote>
  271.  
  272. <Note: Compilers can detect and warn against the use of implicit
  273. promotions of boole to int.>
  274.  
  275. ======================================================================
  276. Add a new section after 4.5 (Arithmetic Conversions) as follows:
  277.  
  278. <begin quote>
  279.  
  280. 4.x Logical Conversions
  281.  
  282. In many contexts, an expression having pointer type or non-boolean
  283. arithmetic type will appear where a value of boolean type is expected.
  284. In these circumstances, a value of pointer type is converted to the
  285. boolean value 0f if and only if the pointer value is that of the null
  286. pointer.  A value of arithmetic type is converted to the boolean value
  287. 0f if and only if the value is zero.
  288.  
  289. <Note: Compilers can detect and warn against the use of implicit
  290. conversions of arithmetic and pointer types to boole.>
  291.  
  292. ======================================================================
  293. In 5.2.5 (Increment and Decrement), replace the fourth sentence of the
  294. first paragraph by:
  295. <begin quote>
  296.  
  297. After the result is noted, the object is incremented by 1, if
  298. non-boolean, or inverted, if boolean.
  299.  
  300. <end quote>
  301.  
  302. ======================================================================
  303. In 5.3 (Unary operators), replace the penultimate paragraph by:
  304. <begin quote>
  305.  
  306. The operand of the operator ! must have arithmetic, pointer, or
  307. boolean type.  For arithmetic types, its value is 0t if its operand
  308. is zero, 0f otherwise.  For pointer types, its value is 0t if its
  309. operand is the null pointer, 0f otherwise.  For boolean types, its
  310. value is the logical negation of its operand.
  311.  
  312. <end quote>
  313.  
  314. ======================================================================
  315. In 5.3.1 (Increment and Decrement), replace the first sentence of the
  316. first paragraph by:
  317. <begin quote>
  318.  
  319. The operand of prefix ++ is incremented by 1 if arithmetic, or
  320. inverted if boolean.
  321.  
  322. <end quote>
  323.  
  324. ======================================================================
  325. In 5.9 (Relational Operators), change the second paragraph to:
  326. <begin quote>
  327.  
  328. The operands must have arithmetic or pointer type.  The operators <
  329. (less than), > (greater than), <= (less than or equal to), and >=
  330. (greater than or equal to) all yield 0f if the specified relation is
  331. false and 0t if it is true.  The type of the result is boole.
  332.  
  333. <end quote>
  334.  
  335. ======================================================================
  336. In 5.10 (Equality Operators), change the second sentence of the first
  337. paragraph to:
  338.  
  339. <begin quote>
  340.  
  341. (Thus a<b == c<d is 0t whenever a<b and c<d have the same truth-value.)    
  342.  
  343. <end quote>
  344.  
  345. ======================================================================
  346. In 5.14 (Logical AND Operator), replace the two paragraphs by:
  347.  
  348. <begin quote>
  349.  
  350. The && operator groups left-to-right.  It returns 0t if both its
  351. operands are 0t, 0f otherwise.  Unlike &, && guarantees left-to-right
  352. evaluation; moreover the second operand is not evaluated if the first
  353. operand evaluates to 0f.
  354.  
  355. The operands each have boolean type.  The result is a boole.  All side
  356. effects of the first expression happen before the second expression is
  357. evaluated.
  358.  
  359. <end quote>
  360.  
  361. <Note: Logical conversion (4.x) permits any arithmetic or pointer type
  362. to appear as an operand, to be converted to boolean type.>
  363.  
  364. ======================================================================
  365. In 5.15 (Logical OR Operator), replace the two paragraphs by:
  366.  
  367. <begin quote>
  368.  
  369. The || operator groups left-to-right.  It returns 0t if either of its
  370. operands are 0t, 0f otherwise.  Unlike |, || guarantees left-to-right
  371. evaluation; moreover the second operand is not evaluated if the first
  372. operand evaluates to 0t.
  373.  
  374. The operands each have boolean type.  The result is a boole.  All side
  375. effects of the first expression happen before the second expression is
  376. evaluated.
  377.  
  378. <end quote>
  379.  
  380. <Note: Logical conversion (4.x) permits any arithmetic or pointer type
  381. to appear as an operand, to be converted to boolean type.>
  382.  
  383. ======================================================================
  384. In 5.16 (Conditional Operator), replace the first paragraph by:
  385.  
  386. <begin quote>
  387.  
  388. Conditional expressions group right-to-left.  The first expression
  389. must have boolean type.  It is evaluated and if it is false, the
  390. result of the conditional expression is the value of the second
  391. expression, otherwise that of the third expression.  All side effects
  392. of the first expression happen before the second or third expression
  393. is evaluated.
  394.  
  395. <end quote>
  396.  
  397. <Note: Logical conversion (4.x) permits any arithmetic or pointer type
  398. to appear as the first operand, to be converted to boolean type.>
  399.  
  400. ======================================================================
  401. In 5.17 (Assignment Operators), add to the list of assignment
  402. operators "&&=" and "||=".
  403.  
  404. ======================================================================
  405. In 6.4.1 (The if Statement), change the first two paragraphs to:
  406. <begin quote>
  407.  
  408. The expression must be of boolean type or of a class type for which an
  409. unambiguous conversion to boolean type exists (12.3).
  410.  
  411. The expression is evaluated and if it is true, the first substatement
  412. is executed.  If else is used, the second substatement is executed if
  413. the expression is false.  The else ambiguity is resolved by connecting
  414. an else with the last encountered else-less if.
  415.  
  416. <end quote>
  417.  
  418. <Note: Logical conversion (4.x) permits any arithmetic or pointer type
  419. to appear as the expression, to be converted to boolean type.>
  420.  
  421. ======================================================================
  422. In 6.5.1 (The while Statement), change the first two paragraphs to:
  423. <begin quote>
  424.  
  425. In the while statement the substatement is executed repeatedly until
  426. the value of the expression becomes false.  The test takes place
  427. before each executeion of the statement.
  428.  
  429. The expression must be of boolean type or of a class type for which an
  430. unambiguous conversion to boolean type exists (12.3).
  431.  
  432. <end quote>
  433.  
  434. <Note: Logical conversion (4.x) permits any arithmetic or pointer type
  435. to appear as the expression, to be converted to boolean type.>
  436.  
  437. ======================================================================
  438. In 6.5.2 (Do statement), change the first two paragraphs to:
  439. <begin quote>
  440.  
  441. In the do statement the substatement is executed repeatedly until
  442. the value of the expression becomes false.  The test takes place
  443. after each executeion of the statement.
  444.  
  445. The expression must be of boolean type or of a class type for which an
  446. unambiguous conversion to boolean type exists (12.3).
  447.  
  448. <end quote>
  449.  
  450. <Note: Logical conversion (4.x) permits any arithmetic or pointer type
  451. to appear as the expression, to be converted to boolean type.>
  452.  
  453. ======================================================================
  454. In 6.5.3 (The for Statement), change "zero" to "false" in the first
  455. paragraph.  Change the last sentence of the first paragraph to:
  456. <begin quote>
  457.  
  458. The first expression must be of boolean type or of a class type for
  459. which an unambiguous conversion to boolean type exists (12.3).
  460.  
  461. <end quote>
  462.  
  463. Change the second sentence, second paragraph to:
  464. <begin quote>
  465.  
  466. A missing expression-1 makes the implied while clause equivalent to
  467. while(0t).
  468.  
  469. <end quote>
  470.