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.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,381b38831db17ac9 X-Google-Attributes: gid103376,public X-Google-ArrivalTime: 2001-12-27 07:35:26 PST Path: archiver1.google.com!news1.google.com!sn-xit-02!sn-post-01!supernews.com!corp.supernews.com!not-for-mail From: "Matthew Heaney" Newsgroups: comp.lang.ada Subject: Re: Who is wrong, me or GNAT? :-) Date: Thu, 27 Dec 2001 10:39:40 -0500 Organization: Posted via Supernews, http://www.supernews.com Message-ID: References: X-Priority: 3 X-MSMail-Priority: Normal X-Newsreader: Microsoft Outlook Express 5.50.4807.1700 X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4807.1700 X-Complaints-To: newsabuse@supernews.com Xref: archiver1.google.com comp.lang.ada:18335 Date: 2001-12-27T10:39:40-05:00 List-Id: > 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;