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=0.7 required=5.0 tests=BAYES_00,INVALID_MSGID, PDS_OTHER_BAD_TLD autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,ef86287aa487b07a X-Google-Attributes: gid103376,public From: Matthew Heaney Subject: Re: Pb with use of redefined "=" operator Date: 1998/11/05 Message-ID: #1/1 X-Deja-AN: 408524435 Sender: matt@mheaney.ni.net References: <363F62F3.3FF7@club-internet.fr> <3640B520.D7BEEE72@elca-matrix.ch> NNTP-Posting-Date: Wed, 04 Nov 1998 18:52:29 PDT Newsgroups: comp.lang.ada Date: 1998-11-05T00:00:00+00:00 List-Id: Mats Weber writes: > Matthew Heaney wrote: > > > ALWAYS import equality for any non-tagged formal type. In the data > > structure library I'm building, every private type is imported as [snip] > I would advise against this, because predefined equality will reemerge > in other situations, such as this: > > type Pair is > record > X, Y : Item_Type; > end record; > > "=" (Pair, Pair) will use the predefined equality on Item_Type, so that > you have to write a new "=" function for Pair. This makes it very hard > to check that the code is correct (i.e. every record/array declaration > that contains a generic formal type must have its own redefined "="). > > My advice is that you must know about the reemergence problem and never > instantiate a generic with a type whose predefined "=" does not work. > You can often do this it using tagged types. I make it a point that when I create a composite type --an abstract data type, or "open," as in your example-- that I guarantee equality will compose. It is for this reason that I always implement (the full view of) ADTs as tagged, even if the partial view is not itself tagged. Mats is correct in pointing out that even if you do import the equality operator, and you use the imported type as the component of an internal composite type, that the predefined equality STILL reemerges. But the solution is trivial: just don't use equality for the composite type! What I do is, always declare the equality for composite types as abstract: generic type Item_Type is private; with function "=" (L, R : Item_Type) return Boolean is <>; package Stacks is ... private type Pair is record X, Y : Item_Type; end record; function "=" (L, R : Pair) return Boolean is abstract; This way, I won't forget that predefined equality reemerges in Pair, nor will the unwary maintenance programmer forget either (because the compiler will tell him when he does forget). For example, for bounded stack implemented as an array, I do something like: private type Item_Array is array (Positive range <>) of Item_Type; function "=" (L, R : Item_Array) return Boolean is abstract; type Stack_Type is tagged record Items : Item_Array; Top : Natural := 0; end record; end Stacks; package body Stacks is function "=" (L, R : Stack_Type) return Boolean is begin if L.Top = R.Top then return False; end if; for I in 1 .. L.Top loop if L.Items (I) /= R.Items (I) then return False; end if; end loop; return True; end "="; ... This stack equality operator works, because the equality operator for the item array type is NOT used (and can't be, because it doesn't exist). The imported equality op for Item_Type is used, and thus equality for the stack type composes. So my advice _is_ to freely instantiate generics with your equality operation --even if it doesn't compose-- because the generic should be written so that it ONLY uses the equality op passed in. There is no problem with this approach, and the client does not have to implement the generic actual type as tagged.