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=-1.3 required=5.0 tests=BAYES_00,INVALID_MSGID autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,9a7e0c43216f4def X-Google-Attributes: gid103376,public From: Matthew Heaney Subject: Re: "out" or "access" Date: 1998/10/30 Message-ID: #1/1 X-Deja-AN: 406738320 Sender: matt@mheaney.ni.net References: <908956499.754394@dedale.pandemonium.fr> <70mo3h$gll$1@cf01.edf.fr> <71cjab$ka8$1@nnrp1.dejanews.com> NNTP-Posting-Date: Fri, 30 Oct 1998 09:38:03 PDT Newsgroups: comp.lang.ada Date: 1998-10-30T00:00:00+00:00 List-Id: dennison@telepath.com writes: > In article , > Robert A Duff wrote: > >> But how about this workaround: declare New_Iterator to take an 'in' >> parameter of type Root_Queue. (Presuming you really do want an >> iterator that can't modify the thing it's iterating over.) So it's >> dispatching, which you want. Inside the various overridings of it, >> you will normally have to do 'Unchecked_Access to produce a pointer >> to the thing, which > > I must be missing something here. Isn't it possible that taking an > 'Unchecked_Access of an in parameter will just give you a pointer to a > copy of the object on the stack, which will disappear when the > procedure ends? Or are you saying to do a ".all'Unchecked_Access" on > the in parameter? We're talking about tagged types here, and there are special rules that apply to objects of a tagged type. The RM mandates that tagged types be passed by reference, and so tagged types passed as subprogram arguments are "implicitly aliased." That's why you can say: procedure Op (O : in T) is -- T is a tagged type type TA is access constant T; OA : constant TA := O'Access; begin without O being declared as "access T" --because T is tagged. Ditto for procedure Op (O : in out T) is type TA is access all T; OA : constant TA := O'Access; begin The RM also recommends that implementations "deliver a useful result" when you take the O'Address of a by-reference type (tagged types, limited types) passed as a subprogram parameter. That's why Sys.Addr_To_Acc_Conv can be used to work around this problem. You don't ever have to pass tagged types as access parameters --unless you need the operation to dispatch. My problem is I need to do this: procedure Visit (S : Stack'Class) is I : Iterator'Class := Initialize (S'Access); begin where Initialize is a function that takes a _constant_ access parameter and returns an iterator (whose type is class-wide). The problem is ... I can't do that, because access constant parameters don't exist in the language. The workaround is to pass the argument as an in param --not access constant param-- so it will dispatch, then use Addr_To_Acc_Conv to turn that into a useful pointer: function Initialize (S : Stack) return Iterator'Class; This func is primitive for type Stack, and therefore it dispatches: package Stacks.My_Stacks is type My_Stack is new Stack with private; type My_Iterator is new Iterator with private; function Initialize (S : My_Stack) return Iterator'Class; ... private ... package Conv is new Sys.Addr_To_Acc_Conv (My_Stack); type My_Iterator is new Iterator with record Stack : Conv.Object_Pointer; Index : ; end record; function Initialize (S : My_Stack) return Iterator'Class is begin return My_Iterator'(To_Pointer (S'Address), S.Top); end; So now the iterator object contains a pointer to the stack object passed in. The works --and I'm not unhappy with it-- it's just that there's no way to prevent dangling references, as you can with access parameters. The declaration procedure Print (S : Stack'Class) is Iter : Iterator'Class := Start_At_Top (S); begin doesn't make it obvious that the _address_ of S is being looked at, and that object Iter contains a pointer to S. That's why it's important to make sure that the stack object lives at least as long as the iterator, or else a dangling reference will occur. I'd much rather say procedure Print (S : Stack'Class) is Iter : Iterator'Class := Start_At_Top (S'Access); begin because it states explicitly that I'm manipulating a reference, but I can't do that, because the language doesn't allow it. So although technically speaking you don't _need_ access constant parameters --because an in param dispatches, and you can sensibly take the address of a tagged type passed as a param-- having access constant parameters is still _strongly_ desireable. It frustrates me that you can't implement a factory method for an iterator, without having to use back-door methods.