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-Thread: 103376,dad94612ff745427 X-Google-Attributes: gid103376,public X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news2.google.com!postnews.google.com!j73g2000cwa.googlegroups.com!not-for-mail From: "Ludovic Brenta" Newsgroups: comp.lang.ada Subject: Re: Instantiating private types with discriminants? Date: 10 May 2006 02:09:58 -0700 Organization: http://groups.google.com Message-ID: <1147252198.138173.203910@j73g2000cwa.googlegroups.com> References: NNTP-Posting-Host: 212.190.145.10 Mime-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" X-Trace: posting.google.com 1147252203 14721 127.0.0.1 (10 May 2006 09:10:03 GMT) X-Complaints-To: groups-abuse@google.com NNTP-Posting-Date: Wed, 10 May 2006 09:10:03 +0000 (UTC) In-Reply-To: User-Agent: G2/0.2 X-HTTP-UserAgent: Mozilla/5.0 (X11; U; SunOS sun4u; fr-FR; rv:1.6) Gecko/20040116,gzip(gfe),gzip(gfe) X-HTTP-Via: 1.1 SEVPXS01 Complaints-To: groups-abuse@google.com Injection-Info: j73g2000cwa.googlegroups.com; posting-host=212.190.145.10; posting-account=ZjNXewwAAADyBPkwI57_UcX8yKfXWOss Xref: g2news2.google.com comp.lang.ada:4171 Date: 2006-05-10T02:09:58-07:00 List-Id: rick H writes: > Dmitry A. Kazakov wrote: > > BTW, You should probably make Put a primitive operation of General_T. Then > > the whole could look like simply: > > > > Put (Var_A.all); -- Do what have to be done > > I'm still a bit new to Ada terminology - does "making Put a primitive > operation" mean doing this kind of thing with a generic package... > type Fred is new Integer; > package Fred_IO is new Ada.Text_IO.Integer_IO (Fred); > use Fred_IO; > If that's right - how would I do this in my example? I'm puzzled > because Var_A.all.Data will resolve to either an Integer or a Float at > run-time. Have I got to declare two new packages - one against > Integer_IO and one for Float_IO and let the dispatcher get it right > at run-time? A "primitive operation" of a type T is a subprogram that: - takes a parameter of type T or "access T", or returns a result of type T or "access T" - is declared in the same package specification as T (same declarative region, really) If these conditions are met, then the operation is primitive. If, in addition, T is tagged, then a call to a primitive operation dispatches dynamically at run time according to the exact type T. Essentially, the compiler does the tag comparison and dispatching for you. So you could write: package P is type T is tagged null record; procedure Put (Item : in T); -- primitive operation type Type_A is new T with Data : Integer; end record; procedure Put (Item : in Type_A); -- primitive operation type Type_B is new T with Data : Float; end record; procedure Put (Item : in Type_B); -- also primitive end P; package body P is procedure Put (Item : in T) is begin null; end Put; -- we could also have declared this procedure abstract procedure Put (Item : in Type_A) is begin Ada.Integer_Text_IO.Put (Item.Data); end Put; procedure Put (Item : in Type_B) is begin Ada.Float_Text_IO.Put (Item.Data); end Put; end P; with P; procedure Simple_Case is Var_A : P.T'Class := ...; -- class-wide type: could be T, Type_A or Type_B begin P.Put (Var_A); -- dynamic dispatch to suitable version of Put end Simple_Case; You can compare Ada's primitive operations with "virtual member functions" in C++. There are however two differences: - in C++, you need pointers or references to dispatch dynamically. In Ada, you can also dispatch with plain variables, as illustrated above. - in C++, all calls done through a pointer or reference dispatch dynamically. In Ada, the call dispatches if and only if the actual parameter is of a class-wide type, i.e. is declared like in my example: Var_A : P.T'Class. In other words, in C++, all types are implicitly class-wide, not in Ada. with P; procedure Simple_Case is Var_A : P.T'Class := ...; -- class-wide type Var_B : P.Type_B; -- specific type Var_T : P.T; -- specific type, contrast with Var_A begin P.Put (P.Type_A (Var_A)); -- explicit type conversion with check, then *static* dispatch P.Put (Var_B); -- static dispatch P.Put (Var_T); -- static dispatch to the null procedure end Simple_Case; -- Ludovic Brenta.