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: 109fba,f92fbb4a0420dd57 X-Google-Attributes: gid109fba,public X-Google-Thread: 103376,f92fbb4a0420dd57 X-Google-Attributes: gid103376,public From: adam@irvine.com (Adam Beneschan) Subject: Re: some questions re. Ada/GNAT from a C++/GCC user Date: 1996/03/29 Message-ID: <4jht4r$tpo@krusty.irvine.com>#1/1 X-Deja-AN: 144916142 references: <315AC5E7.3A77@escmail.orl.mmc.com> organization: /z/news/newsctl/organization newsgroups: comp.lang.ada,comp.lang.c++ Date: 1996-03-29T00:00:00+00:00 List-Id: Ted Dennison writes: >> When I make two different instantiations of a generic package with the >> same arguments, I understand the compiler treats them formally as two >> different packages, which is OK with me. However, I'd appreciate >> knowing the compiler wouldn't actually output two redundant copies of >> the corresponding (identical?) machine code, but instead share the >> code. I saw somewhere that the compiler is given considerable freedom >> to share one instantiation between several arguments if it thinks it's >> appropriate, which is also OK with me. However, I haven't seen any >> guarantee that the compiler won't output redundant copies for >> instantiations with identical arguments. Is there such a guarantee? > >If you want a guarantee, put the code you want shared in a non-generic >package or procedure, and call it from your generic package or >procedure. I don't think this will always work, at least not cleanly. Suppose you have a generic whose only generic formal parameter is a private type: generic type T is private; package GENERIC_PACKAGE is ... procedure Do_Something (X : out T); procedure Do_Something_Else (X : in T); ... end GENERIC_PACKAGE; About the only thing the generic package body can do with objects of type T is to move them around. So, ignoring for the moment strange cases like unconstrained arrays, it should be easy for a compiler to generate one copy of Do_Something and Do_Something_Else (and similarly any procedure declared in the package body) for all instantiations of GENERIC_PACKAGE. Each procedure would take the size of T as an extra parameter, and whenever the procedure needs to move objects of type T around, it just does a raw byte copy, using the size parameter. This should run only slightly slower than if the compiler generated a separate copy of Do_Something for every instantiation, and each copy were able to treat the size as a known constant. But suppose you have a compiler that always generates a separate copy of all procedures for each instantiation. How would you write a non-generic shared procedure that you could call from the generic package? procedure Non_Generic_Do_Something (---well, what?) What types would the parameters of this routine be? The only possibilities I can see would be to have this routine take a SYSTEM.ADDRESS and a size parameter, or a byte array type, or some other low-level type. No matter how you do it, the code in GENERIC_PACKAGE, in order to call Non_Generic_Do_Something, would have to use UNCHECKED_CONVERSION or something like that (which doesn't fit my definition of "cleanly"). Even if all you want is to make sure that only one copy of the code is generated when the generic parameters are identical, how can you do this by writing a shared non-generic routine? If, in four different places, you say: package GP1 is new GENERIC_PACKAGE (RECORD_TYPE_1); package GP2 is new GENERIC_PACKAGE (RECORD_TYPE_2); package GP3 is new GENERIC_PACKAGE (RECORD_TYPE_1); package GP4 is new GENERIC_PACKAGE (RECORD_TYPE_2); How could you write the Non_Generic_Do_Something routine, and the generic Do_Something procedure, so that just two versions of the Do_Something code (one to handle RECORD_TYPE_1 and one to handle RECORD_TYPE_2) are generated by the compiler? -- Adam