home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.lang.c++
- Path: sparky!uunet!munnari.oz.au!metro!extro.ucc.su.OZ.AU!maxtal
- From: maxtal@extro.ucc.su.OZ.AU (John MAX Skaller)
- Subject: Re: Give me safe C++
- Message-ID: <1992Dec20.010907.10429@ucc.su.OZ.AU>
- Sender: news@ucc.su.OZ.AU
- Nntp-Posting-Host: extro.ucc.su.oz.au
- Organization: MAXTAL P/L C/- University Computing Centre, Sydney
- References: <1992Dec3.193006.5520@almserv.uucp> <1992Dec6.131757.7448@ucc.su.OZ.AU> <716@ulogic.UUCP>
- Date: Sun, 20 Dec 1992 01:09:07 GMT
- Lines: 191
-
- In article <716@ulogic.UUCP> hartman@ulogic.UUCP (Richard M. Hartman) writes:
- >In article <1992Dec6.131757.7448@ucc.su.OZ.AU> maxtal@extro.ucc.su.OZ.AU (John MAX Skaller) writes:
- >>In article <1992Dec3.193006.5520@almserv.uucp> e3ubec@fnma.COM writes:
- >>>
- >>> I agree. My implication was that if you don't like C++, then
- >>>you should look for a language that does what you want.
- >>
- >> If you are employed by a large firm you may not have any choice.
- >>Many organisations may chose C++ because it is an ISO standard language.
- >>(Well, it will be ...) Therefore, the C++ designers have a responsibility
- >>to make it as decent as possible. For many programmers, C++ will be
- >>the language they are required to use, not the one they are free to choose.
- >
- >Au contraire. The responsibility is to make it as *useful* as
- >possible. Utility and safety are frequently at odds. Look at
- >the difference between Pascal (safe) and C (useful).
-
- And even Pascal was not so safe, eg variant records.
- >
- >Safety (when not being enforced by the language) is to a large
- >extent (IMHO) a matter of good programming practices.
-
- To some extent, yes. But safety enforced by the
- language is sometimes a good thing. For example, you would
- probably agree that type-safe linkage was a Good Thing??
- This is deliberately and strictly enforced by the compiler
- (and linker).
-
- Have you lost something here? Yes, indeed, rapid
- prototyping is much more difficult when routines in
- parts of the code that never get called must still be
- called with correct parameters.
-
- There are other times when enforcing something
- is good because it allows automatic optimisation to be performed,
- and often this also allow guarantees of correctness. For example,
- the pascal for loop is guarranteed to termina, and the
- control variable can always be put in a fast register.
-
- >Like a
- >seemingly ever-growing segment of the general populace, the cry
- >comes "oh powers that be, protect us from ourselves", and thus
- >we get laws requiring people to wear seatbelts. It is no that
- >I am against seatbelts (or safety), but I was perfectly capable
- >of wearing a seatbelt before the law existed.
-
- It is not so simple Australia, which has a national
- health scheme. Here the alternative "If you get hurt in a crash
- and were'nt wearing a safety belt, we'll just let you die"
- would not be considered politically palatable.
-
- Similarly, lots of kids got hurt in bicycle accidents.
- Now its mandatory to wear a helmet. I didnt wear one until
- I had to. Was saving those kids from brain damage such a bad thing?
-
- >Likewise, to remove some of the "sharp
- >edges" from C and C++ would be to gut them of half of their power
- >and usefulness.
-
- No one is talking about preventing you stuffing
- up your software :-) The issue is more to make you declare
- publically and loudly when you do so, so others reading
- your code will know what you have done.
-
- >> This doesn't mean we should not provide facilities in C++
- >>for writing programs which can be checked for safety by the compiler
- >>or run-time system, merely that we should not remove or fail to add
- >>unsafe features which have other advantages.
- >
- >Wait a minute. If you add (or retain) an "unsafe feature" you
- >are defeating your own point! An unsafe feature is an unsafe
- >feature, no matter how you slice it.
-
- No, my point was poorly expressed. I am considering
- adding 'variants', a form of secure union in which it is
- impossible to access the wrong component.
-
- variant V [V1, V2] v=V1(2);
- select(v){
- type(V1 v1) { ... }
- type(V2 v2) { ... }
- };
-
- Here you simply cannot access the wrong type, unlike an ordinary
- union. COmpletely safe.
-
- What I'm saying is that
-
- a) ordinary unions stay.
- I'm not removing them just because they're not safe.
- b) variants are needed because they allow safety not available
- using unions. They're also more efficient.
-
- >
- >
- >> In particular where commonly used unsafe idioms are actually
- >>the bast available technique, we should look at what sort of language
- >>extension would facilitate expression of the idiom in a safe way.
- >
- >But we would not change the language to outlaw the unsafe idiom?
-
- Well, in this case I would not, because the idiom for
- variants is only ONE use of unions.
-
- >Then the language is still unsafe.
-
- Yes, in this case. But lots of programs whose correctness
- was uncertain in this area could not be written in such a way to
- be absolutely certain that there were no errors. You wouldn't
- *have* to do this, of course.
-
- The 'variants' proposal makes it possible for the compiler
- to tell you if you stuff up, just like type-safe linkage.
- Using unions means you have to verify every line of code by hand.
-
- >
- >> A simple (??) language extension would allow static checking of
- >>this method. The designers and users must chose if the added language
- >>complexity is worth it. What do you think?
- >>
- >> class PayRec;
- >> class ContractorRec;
- >> class DirectorRec;
- >> variant PayRec [EmployeeRec, ContractorRec, DirectorRec];
- >>
- >> PayRec* P;
- >>
- >> for(int i=0; i<nP; ++i)
- >> {
- >> cout << P[i]->name; // common field
- >> select(P[i]) // type sensitive code below
- >> {
- >> type(EmployeeRec *E) { ... }
- >> type(ContractorRec *C) { ... }
- >> type(DirectorRec *D) { ...}
- >> }
- >> }
- >
- >With no language extensions, this seems equivilant to what you
- >have proposed (note: off the top of my head, incomplete, uncompiled
- >example follows -- standard disclaimers apply):
- >
- >class PayRec {
- > public:
- > enum PayRecType { Employee, Contractor, Director };
-
- >class EmployeeRec : public PayRec {
- >...
- >};
-
- Here is where your example fails. How do you know in advance
- to derive EmployeeRec from PayRec?
-
- In the case of a union or variant, thats is done
- after EmployeeRec is locked away in the library.
-
- You example is more or less correct (except you forgot
- to downcast) in the sense that it works.
- You will note that your code is not secure.
- There is no reason to use virtual functions or a common
- base here, no inheritance or other relationship exists
- between these types.
-
- The equivalent idiom is to use
-
- struct PayRec {
- enum {Employee, Contractor, Director} tag;
- union {
- Employee E;
- Contractor C;
- Director D;
- };
- };
-
- and a switch, which doesnt require the downcast (which incidentally
- you forgot), and can be done after Employee, Contractor and Director
- have been closed off and locked away.
-
- Both this method and yours, however suffer from the
- problem of being unsafe, and messy to code. It much easier
- to say
-
- variant PayRec [Employee, Contractor, Director];
-
- isnt it?
-
- --
- ;----------------------------------------------------------------------
- JOHN (MAX) SKALLER, maxtal@extro.ucc.su.oz.au
- Maxtal Pty Ltd, 6 MacKay St ASHFIELD, NSW 2131, AUSTRALIA
- ;--------------- SCIENTIFIC AND ENGINEERING SOFTWARE ------------------
-