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,4f4ee91990d68693 X-Google-Attributes: gid103376,public From: Matthew Heaney Subject: Re: Usefulness of classwide "out" parameter Date: 1999/03/15 Message-ID: #1/1 X-Deja-AN: 455159664 Sender: matt@mheaney.ni.net References: <7cikku$d4k$1@nnrp1.dejanews.com> NNTP-Posting-Date: Mon, 15 Mar 1999 02:13:18 PDT Newsgroups: comp.lang.ada Date: 1999-03-15T00:00:00+00:00 List-Id: 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. You can subscribe to the patterns list by sending a message with the body subscribe patterns to the ACM mailing list server.