Path: utzoo!utgpu!news-server.csri.toronto.edu!mailrus!uunet!mcsun!ukc!dcl-cs!aber-cs!odin!pcg From: pcg@cs.aber.ac.uk (Piercarlo Grandi) Newsgroups: comp.lang.c++ Subject: Re: Static consts within classes? Message-ID: Date: 29 Jun 90 13:10:28 GMT References: <10460@batcomputer.tn.cornell.edu> <274@taumet.com> Sender: pcg@aber-cs.UUCP Followup-To: comp.lang.c++ Organization: Coleg Prifysgol Cymru Lines: 113 In-reply-to: steve@taumet.com's message of 27 Jun 90 16:15:42 GMT In article <274@taumet.com> steve@taumet.com (Stephen Clamage) writes: In article pcg@cs.aber.ac.uk (Piercarlo Grandi) writes: >Ahhh. Too bad :-). Stroustrup loves enums, indeed they have been made >local scope to a class definition as a special case because of that. Too >bad, because consts make, IMNHO, enums redundant in C/C++... Not at all redundant. The declarations [ ... explains that, unlike ANSI C, int values cannot be assigned to enums without casting ... ] Enums thus provide greater type safety where desired. A very small dose of it, and only thanks to yet another special case rule, and with significan disadvantage. It is otherwise stated very clearly that enums are integral types, and can be used in any context where another integral type *could* be used; the reverse is true as well; what is not possible is to use non enums where an enum *must* be used. But is that important? To me it is more important to be able to specify the length of an integral type, which cannot be done (why ever?) for an enum. Maybe redundant is too strong a word, but frankly the small added type security (forbidding conversions in just one direction) is a very small advantage, and the loss of length specificaiton is bad; what happens in practice is that one ends writing things like: enum { one, some, many; }; typedef char unsigned ordinal; ordinal thumbrule[CASES] = { one, one, some, one, many ... }; And bang goes the type security. What one can do is to use a struct with bitfields, but I see it as very unnatural. Also, using a class with const static members gives qualification to the type's values. class eyes { static const char unsigned none, one, two, argos; }; class ordinal { static const char unsigned one, some, many; }; /* static? */ const char unsigned ordinal::one = 1, ordinal::some = 3, ordinal::many = 999; /* static? */ const char unsigned eyes::none = 0, eyes::one = 1, eyes::two = 2, eyes:argos = 100; Admittedly however with 2.0 and 2.1 also enums are now class local: class eyes { enum { none = 0, one = 1, two = 2, argos = 100 }; }; class ordinal { enum { one = 1, some = 3, many = 999 }; }; But the two things are essentially equivalent, and the former requires less special casing. If you like this kind of type security, why not lobby to make typedef's introduce new types instead of synonyms for old types? Why special case enums, and in one direction only? >Well, I am not even sure that it is legal to have const data members, >whether static or not, and then where they can be initialized. Let me make it obvious: I know that as of now you can, as a special case, have non static const class data members. But the problem is that in practice this depends on the language release, compiler, compiler release, and the phase of the moon. Again I beg to differ. Const data members, static or not, are perfectly legal, and initialized the same way as any other const object. Ahem. Not entirely. Non static const members can only be initialized in the constructor, and then only in the special initialization list of the constructor, as you comment in your example. In other words, const non static members are only legal for classes with constructors. Nothing is said of const static members... For example, what is the linkage of a static const internal of external? const by default implies internal, but static members are by default external. Which prevails? Maybe an answer exists, but like so many other things in C++ it is far from obvious. The practical answer is not to rely on underspecified features unless you are prepared to stick to the one compiler, one release principle. Example: struct mystruct { [ ... ] static const int j; // only one copy in whole program static int k; // only one copy in whole program [ ... ] }; file mystruct.c: #include "mystruct.h" static const int mystruct::j = 1; // initialized here only static int mystruct::k = 2; // initialized here only [ ... ] Ahhh. This is similar to the example I have used myself. But then I ask again: why did you put 'static' in the two definitions? Is that legal? What is the effect on the linkage of the definitions? As I have pointed out, it can be shown that G++ 1.36.x allows but essentially ignores the static in the definition, and makes the rule that says static members are external prevail (but only for static const or uninitialized static; linkage becomes internal for static non const but initialized, and for static functions). This is all I am prepared to rely upon; I will not rely upon any other compiler, compiler release, language version to do the same thing. Frankly, this is big nuisance time. I'd like to specify the linkage of a "static" class member. Maybe having chosen static for "static" calss members has not been very wise, because it has preempted the other meaning. Oh, curse the overloading of symbols and reserved words in C++. -- Piercarlo "Peter" Grandi | ARPA: pcg%cs.aber.ac.uk@nsfnet-relay.ac.uk Dept of CS, UCW Aberystwyth | UUCP: ...!mcsun!ukc!aber-cs!pcg Penglais, Aberystwyth SY23 3BZ, UK | INET: pcg@cs.aber.ac.uk