comp.lang.ada
 help / color / mirror / Atom feed
From: "Matthew Heaney" <mheaney@on2.com>
Subject: Re: Who is wrong, me or GNAT? :-)
Date: Thu, 27 Dec 2001 10:39:40 -0500
Date: 2001-12-27T10:39:40-05:00	[thread overview]
Message-ID: <u2mftuap1kkfa1@corp.supernews.com> (raw)
In-Reply-To: c25V7.2353$8L1.26553@rwcrnsc52


> Is this a bug in GNAT?  If not, what am I missing?

No, this is not a GNAT bug.

> I was trying to come up with an idiom for inherited constructors for
> descendants of an abstract tagged type, and this seemed like it ought to
do
> the trick (although it suffers from the fact that the intermediate derived
> type, e.g. T1 in this case, would have to override all the abstract
> primitives).

Constructors are never inherited.  If you want a function to return a value
of the type, then you should declare the function in a nested package, or
return a class-wide type.

package P is
   type T is tagged null record;
   package Constructors is
      function Create return T;
   end;
end P;

or

package P is
   type T is tagged null record;
   function Create return T'Class;
end P;


In both of these cases, the operation isn't primitive anymore.

Of course, in the schemata above there's nothing to guarantee that the
client has called your contructor, because he can do this:

declare
   O : P.T;
begin
   null;
end;

You can ensure that the ctor is called by declaring the type with unknown
discriminants:

package P is
   type T (<>) is tagged private;
   function Create return T'Class;
private
   type T is tagged null record;
end P;

Now a client is forced to initialize his object by calling the ctor, or
copying another object:

declare
   Ox : T;  --won't compile
   O1 : T'Class := Create;
   O2 : T'Class := O1;
begin
   null;
end;

You can prevent copies by declaring the type as limited (and indefinite),
and supplying a ctor that returns an access object:

package P is
   type T (<>) is tagged limited private;
   type T_Access is access all T;
   function New_T return T_Access;
   procedure Op (O : access T);
end P;

declare
   O : T_Access := New_T;
begin
   Op (O);
end;

If you're worried about memory leaks, then you can use controlled-ness
somewhere, eg

declare
   O : aliased T_Access := New_T;
   Control : Control_Type (O'Access);
begin
   Op (O);
end;

Here, Control_Type is a type that calls Free in its Finalize operation.
Another technique (which I demonstrated at the AdaUK meeting a few weeks ago
in London) is to use an "auto_ptr" a la C++:

declare
   O : Pointer_Type;
begin
   Set_Pointer (O, New_T);
   Op (+O);
end;

The auto_ptr object allows you to transfer ownership of an access object.
If the auto_ptr still owns an access object during its Finalize, it calls
Free.

You can also use a smart pointer:

declare
   O : Handle_Type := New_T;
begin
   Op (+O);
end;







      parent reply	other threads:[~2001-12-27 15:39 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2001-12-22 19:20 Who is wrong, me or GNAT? :-) Mark Lundquist
2001-12-22 19:28 ` Ed Falis
2001-12-22 21:14   ` Mark Lundquist
2001-12-27 15:39 ` Matthew Heaney [this message]
replies disabled

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