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, REPLYTO_WITHOUT_TO_CC,T_FILL_THIS_FORM_SHORT autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,d0a0c07bfe9948e3 X-Google-Attributes: gid103376,public X-Google-ArrivalTime: 1994-12-29 15:17:53 PST Path: nntp.gmd.de!Germany.EU.net!Munich.Germany.EU.net!ibm.de!kaa.heidelbg.ibm.com!aixssc.uk.ibm.com!watnews.watson.ibm.com!ncohen From: ncohen@watson.ibm.com (Norman H. Cohen) Newsgroups: comp.lang.ada Subject: Re: How is this done? Date: 23 Dec 1994 15:26:34 GMT Organization: IBM T.J. Watson Research Center Distribution: world Message-ID: <3deq7a$1hrc@watnews1.watson.ibm.com> References: <1994Dec22.113500.14671@driftwood.cray.com> Reply-To: ncohen@watson.ibm.com NNTP-Posting-Host: rios8.watson.ibm.com Date: 1994-12-23T15:26:34+00:00 List-Id: In article <1994Dec22.113500.14671@driftwood.cray.com>, brh@cray.com (Brian R. Hanson) writes: |> Given the following package and procedure definitions - ... [example omitted] |> What needs to be done to have New_List.View use the View procedure |> that is the result of the type definition for New_List.List? This is a wicked problem! Let me rephrase the example more simply. (By the way, these things are easier to read if you show the declaration of a package BEFORE its body.) generic package Template is type T1 is ...; procedure P (X: in T1); end Template; with Template; pragma Elaborate (Template); package Client is type T2 is private; procedure P (X: in T2); private package Instance is new Template; -- There is a procedure Instance.P with an Instance.T1 parameter type T2 is new Instance.T1; -- A procedure P with a T2 parameter is inherited from Instance.T1 -- and implicitly declared here. end Client; Brian wants Client.P to behave like Instance.P. He observes that if he doesn't provide a body for Client.P he gets a compile-time error, but if he does, "the body overrides" the inherited version. The declaration of P in the Client package declaration obligates the Client package body (in the absence of an Interface or Import pragma) to provide an implementation. This implementation must be a subprogram body in Ada 83; it is also allowed to be a renaming declaration in Ada 95. However, there are two distinct declarations immediately within package Client for a procedure named P. One is the explicit declaration following the private-type declaration. The other is the implicit declaration of the inherited procedure immediately following the derived-type declaration. Because both declarations are for a procedure with one parameter, of type T2, the declarations are "homographs". Two homographs are not allowed in the same "declarative region" unless at leat one of them is implicit. (In this case the the declaration and body of Client together form a single declarative region.) Given an explicit and implicit homograph in the same declarative region, the explicit one hides the implicit one, starting at the point of the explicit declaration. In this case, the version of P inherited from Instance.T1 is "born hidden". It is theoretically there, but there is no way to refer to it. Thus it is not the body of Client.P that overrides the inherited P; it is the declaration of P in the visible part of Client that does so. The most straightforward solution is to use different names for the operation provided by Client and the operation provided by instances of Template: with Template; pragma Elaborate (Template); package Client is type T2 is private; procedure Q (X: in T2); -- previously named P private package Instance is new Template; -- There is a procedure Instance.P with an Instance.T1 parameter type T2 is new Instance.T1; -- A procedure P with a T2 parameter is inherited from Instance.T1 -- and implicitly declared here. end Client; package body Client is procedure Q (X: in T2) is begin P(X); -- calls the procedure inherited from Instance.T1 end Q; -- Or, in Ada 95, simply -- procedure Q(X: in T2) renames P; end Client; If there is a requirement to use the same name in Template and Client, you can do this: with Template; pragma Elaborate(Template); package Intermediate is package Instance is new Template; type T_1_Point_5 is new Instance.T1; procedure Q (X: in T2) renames P; -- Provide an alternative name that won't get hidden. end Intermediate; with Intermediate; package Client is type T2 is private; procedure P (X: in T2); private type T2 is new Intermediate.T_1_Point_5; -- Procedures P and Q, each with a T2 parameter, are inherited -- from Intermediate.T_1_Point_5 and implicitly declared here. -- The declaration of P is hidden as before, but the declaration -- of Q is not. end Client; package body Client is procedure P (X: in T2) is begin Q (X); end P; -- Or, in Ada 95, simply -- procedure P (X: in T2) renames Q; end Client; (Package Intermediate, type T_1_Point_5, and the view of P named Q are part of the implementation of Client, not meant for use outside of Client. In Ada 95, package Client could be made a visible child, and package Intermediate a private child, of an empty parent package, say Root. Root.Intermediate and the facilities it provides to Root.Client would then be hidden from the rest of the program.) Other alternatives include instantiating Template and deriving T2 from Instance.T1 in the VISIBLE part of Client (so that P is not declared explicitly in Client, but the implicit declaration of the inherited version is available to all users of Client); or, in Ada 95, evaluating whether Template can be turned into a nongeneric package providing an abstract tagged type, and replacing instantiations by extensions of this type. -- Norman H. Cohen ncohen@watson.ibm.com