comp.lang.ada
 help / color / mirror / Atom feed
From: Matthew Heaney <matthew_heaney@acm.org>
Subject: Re: Usefulness of classwide "out" parameter
Date: 1999/03/15
Date: 1999-03-15T00:00:00+00:00	[thread overview]
Message-ID: <m3yakzawh9.fsf@mheaney.ni.net> (raw)
In-Reply-To: 7cikku$d4k$1@nnrp1.dejanews.com

okellogg@my-dejanews.com writes:

> Has anyone ever used a classwide subprogram parameter with mode "out"?

No, because it's not very useful.

> For example,
> 
>     type Mytype is tagged null record;
>     procedure Proc (Result : out Mytype'Class);
> 
> The problem I have with this is, I cannot assign another variable
> to the out parameter (that would change the tag, which is not
> possible.)

The only thing you could do assign the object, if the tag happened to
match.  Otherwise, you'll just get tag check errors.

> Am I correct in asserting that classwide parameters of mode "out" are
> not terribly useful?

That is indeed the case.


> What would a practical application of this look like?

Can you return a class-wide type as a function return instead?
Something like:

  function Func return MyType'Class;

 
> I am appending an example that shows the problem.

> -- base.ads
> package Base is
>    type Mytype is tagged null record;
>    procedure Proc (Result : out Mytype'Class);
> end Base;

This type is non-limited, so returning a class-wide type as the result
of a function would be OK.

 
> with Base.Derived1, Base.Derived2;
> package body Base is
>    V1 : Base.Derived1.Deriv1;
>    V2 : Base.Derived2.Deriv2;
>    Some_Flag : Boolean := False;
>    procedure Proc (Result : out Mytype'Class) is
>    begin
>       if Some_Flag then
>          Result := V1;   -- GNAT says:
>       else
>          Result := V2;   -- dynamically tagged expression required
>       end if;
>    end Proc;
> end Base;


How about this:

  function Func return Mytype'Class is
  begin
    if Some_Flag then
       return V1;
    else
       return V2;
    end if;
  end Func;

This should be fine for what you're trying to do.  But...

...what you're doing looks suspiciously like the singleton pattern.  If
you're returning the value of a statically allocated instance, then you
can just as easily return a pointer to it:

 type Mytype_Access is access constant Mytype'Class;

 package body P is

   V1 : aliased D1;
   V2 : aliased D2;
   
   procedure Proc (Result : out Mytype_Access) is
   begin
     if Some_Flag then
       Result := V1'Access;
     else
       Result := V2'Access;
   end Proc;

or

  function Func return Mytype_Access is
  begin
    if Some_Flag then
       return V1'Access;
    else
       return V2'Access;
    end if;
  end Func;

       
If you want to enforce cardinality, or just control how instances are
created, then you can declare the type as limited and indefinite.

Singletons are implemented by returning a pointer to the statically
declared instance in the body, and declaring primitive operations of the
type to take access parameters.

See my most recent post, "State Pattern," in the Mar 99 ACM patterns
archive, for an example of how to do this.  The article "Abstract
Factory Revisited" has lots of info about these idioms too.

<http://www.acm.org/archives/patterns.html>

You can subscribe to the patterns list by sending a message with the
body 

subscribe patterns <your full name>

to the ACM mailing list server.

<mailto:listserv@acm.org>




  parent reply	other threads:[~1999-03-15  0:00 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
1999-03-15  0:00 Usefulness of classwide "out" parameter okellogg
1999-03-15  0:00 ` Joachim Schroeer
1999-03-15  0:00 ` Matthew Heaney [this message]
1999-03-17  0:00 ` Nick Roberts
replies disabled

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