comp.lang.ada
 help / color / mirror / Atom feed
From: Matthew Heaney <matthew_heaney@acm.org>
Subject: Re: "out" or "access"
Date: 1998/10/30
Date: 1998-10-30T00:00:00+00:00	[thread overview]
Message-ID: <m3zpaeqq56.fsf@mheaney.ni.net> (raw)
In-Reply-To: 71cjab$ka8$1@nnrp1.dejanews.com

dennison@telepath.com writes:

> In article <wcc3e87hrl8.fsf@world.std.com>,
>   Robert A Duff <bobduff@world.std.com> 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 : <some index type>;
      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.





  reply	other threads:[~1998-10-30  0:00 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
1998-10-21  0:00 "out" or "access" =:-) Vincent
1998-10-21  0:00 ` Jeff Carter
1998-10-21  0:00   ` Pat Rogers
1998-10-21  0:00     ` Martin C. Carlisle
1998-10-22  0:00       ` Pat Rogers
1998-10-22  0:00     ` Robert A Duff
1998-10-21  0:00 ` dennison
1998-10-21  0:00 ` Tucker Taft
1998-10-22  0:00   ` Pascal Obry
1998-10-29  0:00     ` Robert A Duff
1998-10-29  0:00       ` Matthew Heaney
1998-10-29  0:00         ` Robert A Duff
1998-10-30  0:00           ` dennison
1998-10-30  0:00             ` Matthew Heaney [this message]
1998-10-30  0:00               ` Robert A Duff
1998-10-31  0:00                 ` Matthew Heaney
1998-11-01  0:00                   ` Robert A Duff
1998-11-01  0:00                     ` Matthew Heaney
1998-11-01  0:00                       ` Robert A Duff
1998-11-02  0:00                         ` Matthew Heaney
1998-11-03  0:00                           ` Simon Wright
1998-11-16  0:00                             ` Matthew Heaney
1998-10-31  0:00                 ` dewar
1998-10-31  0:00                   ` Matthew Heaney
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox