stan@kaiser.UUCP (s Lippman) (06/19/89)
My ``C++ Primer'' is based on a draft of Bjarne's
C++ Reference Manual (and matching in-house pre-
release versions Release 2.0). Subsequent to the
delivery of the manuscript a review of the language
definition resulted in a few modifications. This
impacts the book as follows:
p.24 : the keyword ``handle'' is now replaced with
the keyword ``catch'' (also page 430).
p.40 : named enumerations now define unique integral
types. For example,
enum TestStatus { NOT_RUN=-1, FAIL, PASS };
enum Boolean { FALSE, TRUE };
main() {
TestStatus test = NOT_RUN;
Boolean found = FALSE;
test = -1; // error: TestStatus = int
test = 10; // error: TestStatus = int
test = found; // error: TestStatus = Boolean
test = FALSE; // error: TestStatus = const Boolean
int st = test; // ok: implicit conversion
}
for compatibility with prior releases, the 2.0
implementation issues warnings rather than errors.
p. 159: Overloaded functions can now be distinquished by
arguments of an enumeration type. For example,
enum Bool { FALSE, TRUE } found;
enum Stat { FAIL, PASS };
extern void ff( Bool );
extern void ff( Stat );
extern void ff( int );
ff( PASS ); // ff( Stat )
ff( 0 ); // ff( int )
ff( found ); // ff( Bool )
p. 264-265: Class instances of operator new and operator delete
should define arguments of type ``size_t'' rather
than of type long. As Andy Koenig pointed out in a
discussion of these operators, the current 2.0
implementation accepts the long argument and replaces
it with that of size_t.
The class instance of operator delete must define a
return type of void. (There was a brief window when
it was permitted to define an arbitrary return type
-- this section was completed during this window.)
p. 354 : A virtual function invoked within either the constructor
OR destructor of a base class is resolved statically
to the instance defined by the base class. (Thanks
to Andy Koenig for pointing out the destructor case.)
These corrections will be reflected in a subsequent reprinting
of the book.
Stan Lippman
AT&T Bell Laboratories
mcdaniel@uicsrd.csrd.uiuc.edu (Tim McDaniel) (06/20/89)
[I'm sorry if the original cancelled one gets out, too.] In article <883@kaiser.UUCP> stan@kaiser.UUCP (s Lippman) writes: >p.40 : named enumerations now define unique integral > types. For example, > > enum TestStatus { NOT_RUN=-1, FAIL, PASS }; > enum Boolean { FALSE, TRUE }; > > main() { > TestStatus test = NOT_RUN; > Boolean found = FALSE; > > test = -1; // error: TestStatus = int > test = 10; // error: TestStatus = int > test = found; // error: TestStatus = Boolean > test = FALSE; // error: TestStatus = const Boolean > int st = test; // ok: implicit conversion > } I'd like to see more details on what the semantics exactly are. The only examples here are for assignment, but for full clarity, I need to know the results of applying any operator to an enum operand. What happens when I have values and operations like: enum_X <op> enum_X => enum_X ? Y* <op> enum_X => Y* or error? int <op> enum_X => enum_X or error? type var[enum_X]; => tye var[(int) enum_X]; or error? Any other cases I've neglected? Suppose I want to count the number of times NOT_RUN, FAIL, and PASS occur. So I'd actually do something like this: enum TestStatus { NOT_RUN, FAIL, PASS, MAX_TEST }; int status_count[MAX_TEST]; for (TestStatus i = NOT_RUN; i < MAX_TEST; i++) status_count[i] = 0; enum TestStatus rc; while (dotest(&rc)) status_count[rc]++; Is this legal or not? I'd hate to have to muck about with int status_count[(int) MAX_TEST]; ... status_count[(int) rc]++; > int st = test; // ok: implicit conversion Bleah. Are there any other cases in C++ where type var = expr; is not equivalent to type var; var = expr; ? Are there any other possible "implicit conversions"? >p.40 : named enumerations now define unique integral types What's a "named enumeration"? Is typedef enum {FOO, BAR} widget; a named enumeration? What if we have enum {FOO, BAR} a; a = 1; // legal or no? Why are "named" enumerations distinguished from "unnamed" ones? -- "Let me control a planet's oxygen supply, and I don't care who makes the laws." - GREAT CTHUHLU'S STARRY WISDOM BAND (via Roger Leroux) __ \ Tim, the Bizarre and Oddly-Dressed Enchanter \ mcdaniel@uicsrd.csrd.uiuc.edu /\ mcdaniel%uicsrd@{uxc.cso.uiuc.edu,uiuc.csnet} _/ \_ {uunet,convex,pur-ee}!uiucuxc!uicsrd!mcdaniel
ark@alice.UUCP (Andrew Koenig) (06/20/89)
In article <1304@garcon.cso.uiuc.edu>, mcdaniel@uicsrd.csrd.uiuc.edu (Tim McDaniel) writes: > I'd like to see more details on what the semantics exactly are. The > only examples here are for assignment, but for full clarity, I need to > know the results of applying any operator to an enum operand. Every enumerated type is a separate type. When used in a context that requires an integer, a value of an enumerated type is quietly converted to an int. Converting the other way requires a cast. > What happens when I have values and operations like: > enum_X <op> enum_X => enum_X ? If <op> is something like `+', the result is an int. > Y* <op> enum_X => Y* or error? The enum_X value is quietly converted to int; the result is Y*. > int <op> enum_X => enum_X or error? The result is an int. > type var[enum_X]; => tye var[(int) enum_X]; or error? The enum_X is converted to an int. > Suppose I want to count the number of times NOT_RUN, FAIL, and PASS > occur. So I'd actually do something like this: > enum TestStatus { NOT_RUN, FAIL, PASS, MAX_TEST }; > int status_count[MAX_TEST]; OK so far. > for (TestStatus i = NOT_RUN; i < MAX_TEST; i++) > status_count[i] = 0; > > enum TestStatus rc; > while (dotest(&rc)) > status_count[rc]++; It's legal. The only part of this that's questionable is the notion of applying ++ to an enum, but I'm pretty sure that's OK even though the corresponding use of + would require a cast to convert the result back to enum. > Bleah. Are there any other cases in C++ where > type var = expr; > is not equivalent to > type var; > var = expr; > ? Are there any other possible "implicit conversions"? Saying type var = expr; is NEVER equivalent to saying type var; var = expr; The first case creates var and simultaneously initializes it to expr. The second creates var, initializes it to a default value (which is often garbage) and then obliterates that value with `expr.' It is possible to define types for which either of these is legal and the other is illegal. > >p.40 : named enumerations now define unique integral types > What's a "named enumeration"? Is > typedef enum {FOO, BAR} widget; > a named enumeration? What if we have > enum {FOO, BAR} a; > a = 1; // legal or no? No -- you need a cast to convert an integer to an enumerated type. > Why are "named" enumerations distinguished from "unnamed" ones? An unnamed enumeration doesn't give you a useful handle for the type it defines. It defines several objects (the one above defines FOO, BAR, and a) of a nameless type. Since the type is nameless, it's not possible to get at it again. -- --Andrew Koenig ark@europa.att.com