From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-0.8 required=5.0 tests=BAYES_00,INVALID_DATE autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,997050aa5cf64c63 X-Google-Attributes: gid103376,public X-Google-ArrivalTime: 1994-09-27 16:46:26 PST Newsgroups: comp.lang.ada Path: bga.com!news.sprintlink.net!howland.reston.ans.net!europa.eng.gtefsd.com!MathWorks.Com!noc.near.net!inmet!dsd!bobduff From: bobduff@dsd.camb.inmet.com (Bob Duff) Subject: Re: Tagged type feature, or GNAT bug? Message-ID: Sender: news@inmet.camb.inmet.com Organization: Intermetrics, Inc. References: <369hme$e9j@felix.seas.gwu.edu> Date: Tue, 27 Sep 1994 23:22:33 GMT Date: 1994-09-27T23:22:33+00:00 List-Id: In article <369hme$e9j@felix.seas.gwu.edu>, Michael Feldman wrote: >-- CASE 1: array of unconstrained variant records. OK in Ada 83. > > TYPE List IS ARRAY (1..4) OF VariantRec; -- unconstrained variant rec > Stuff: List; > >-- CASE 2: Now an array intended to hold any of the four types >-- (by direct analogy with Case 1) > >-- GNAT rejects this - says the array elements must be constrained GNAT is correct here. The rule is in RM9X-3.6(10), which says the component subtype has to be a definite subtype. Class-wide subtypes are not definite (see 3.3(23) and 3.7(26)). Class-wide subtypes are like discriminated subtypes *without* defaults. > TYPE TaggedList IS ARRAY (1..4) OF TaggedRec'Class; > TaggedStuff: TaggedList; > >-- CASE 3: Array of_pointers_ to tagged records >-- This will compile OK, but seems a gratuitously required use >-- of pointers - very un-Ada-like. > > TYPE TaggedRecPtr IS ACCESS TaggedRec'Class; > TYPE TaggedListPtr IS ARRAY (1..4) OF TaggedRecPtr; > TaggedStuffPtr: TaggedList; That's right -- you have to use pointers (ahem, I mean access types). Basically, "definite" means the compiler knows how much space to allocate. Clearly, the compiler can't know how much space to allocate for a class-wide subtype, because you can add type extensions later, and these can have arbitrary sizes. Since the compiler doesn't know how much space to allocate, you have to use a pointer. Ada, being intended for real-time applications, doesn't like to have implicit pointers, and the corresponding implicit heap allocation. Instead, whenever the compiler doesn't know the size, the language requires the programmer to use pointers, and do the necessary allocations "by hand". In other words, the reason you can't have an array of class-wide is the same reason you can't have an array of unconstrained arrays: type T is array(1..10) of String; -- Illegal! This example makes perfect sense from a logical point of view, but would require implicit heap management by the compiler. Therefore, you have to use an access-to-String type in this example. Same thing for class-wide. Thus, when converting an application that uses discriminants-with-defaults to one that uses class-wide types, you have to introduce pointers. For discriminants-with-defaults, the compiler can see the whole variant record, and can figure out the maximum size. For class-wide subtypes, however, the maximum size is unbounded. There are some compilers that introduce implicit heap allocation for discriminants with defaults. However, that is by no means universal among compilers, and is arguably naughty behavior in a real-time environment. We certainly didn't want to *require* such behavior for class-wide subtypes. Most other OOP languages that I know of have the same restriction -- most (e.g. Smalltalk) use pointer semantics *everywhere*, and the ones that don't (e.g. C++) require the "tag" to be nailed down (and not change) by the time an object is created. In either case, to change a tag normally requires deallocating and reallocating the object -- using pointers. -- Bob Duff bobduff@inmet.com Oak Tree Software, Inc. Ada 9X Mapping/Revision Team (Intermetrics, Inc.)