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,WEIRD_PORT autolearn=ham autolearn_force=no version=3.4.4 X-Google-Thread: 103376,79d6bba6ba97b840 X-Google-NewGroupId: yes X-Google-Attributes: gida07f3367d7,domainid0,public,usenet X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news1.google.com!news1.google.com!npeer02.iad.highwinds-media.com!news.highwinds-media.com!feed-me.highwinds-media.com!news.glorb.com!news2.glorb.com!fu-berlin.de!uni-berlin.de!individual.net!not-for-mail From: Niklas Holsti Newsgroups: comp.lang.ada Subject: Re: Renaming of procedures in a generic instantiation Date: Sun, 26 Sep 2010 09:54:15 +0300 Organization: Tidorum Ltd Message-ID: <8g890nFmqiU1@mid.individual.net> References: Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-Trace: individual.net zcE5EqPbhxg7lVWD6Tq/wQSx9ILIyreqHhjw5JGwIxaJq7LBKC Cancel-Lock: sha1:jPZ09r2YVlVqJ1wRsOZqRp5hvSk= User-Agent: Mozilla-Thunderbird 2.0.0.24 (X11/20100328) In-Reply-To: Xref: g2news1.google.com comp.lang.ada:14260 Date: 2010-09-26T09:54:15+03:00 List-Id: Gene wrote: > I'm confused about an aspect of renaming. It boils out to this little > example: > > with Ada.Containers.Ordered_Sets; > > package Foo is > > type Queue is private; > > procedure Add(Q : in out Queue; Item : in Integer); > > function Is_Empty(Q : Queue) return Boolean; > > private > > package Queues is > new Ada.Containers.Ordered_Sets(Integer, "<", "="); > type Queue is new Queues.Set with null record; > > end Foo; > > package body Foo is > > procedure Add(Q : in out Queue; Item : in Integer) > renames Insert; > > function Is_Empty(Q : Queue) return Boolean > renames Queues.Is_Empty; > > end Foo; > > The renaming in Add "finds" the correct procedure Insert, but the > renaming of Is_Empty fails: > > gnatmake foo.adb > gcc -c foo.adb > foo.adb:6:04: no visible subprogram matches the specification for > "Is_Empty" > foo.adb:6:13: expected private type "Ada.Containers.Ordered_Sets.Set" > from insta > nce at foo.ads:14 > foo.adb:6:13: found type "Queue" defined at foo.ads:16 > gnatmake: "foo.adb" compilation error > > I guess I can see this error because a parameter type conversion is > implied in the renaming. But then why does the renaming of Insert > work correctly? The type derivation type Queue is new Queues.Set with null record; makes type Queue inherit the primitive operations of Queues.Set by implicitly declaring (within package Foo) corresponding operations on type Queue. These include the operation Insert with the profile: procedure Insert ( Container : in out Queue; New_Item : in Integer); This profile matches that of Foo.Add, and so Foo.Add can be a renaming of this Insert. By the way, this implicitly declared Insert (on Queue) has the qualified name Foo.Insert, not Queues.Insert. The type derivation also "tries" to declare implicitly the Is_Empty operation from Queues, with the profile: function Is_Empty (Container : Queue) return Boolean; but this operation clashes with (has the same name and same profile as) the operation Is_Empty that was already and explicitly declared in Foo (before the "private"), so they cannot both be visible. If I understand correctly, the rule RM 8.3(10/1) says that the first, explicit declaration overrides the second, implicit declaration (because the first declaration is not "overridable"). So what saves you in the Insert/Add case is that the operation names are different, which means there is no clash. It is a bit irritating that the "simpler" case, with the same names, does not work in the same way. I have at times had the same problem, where I have been disappointed that implementing a private type as a derived type does not implicitly complete the declarations of matching operations, such as Is_Empty in this example. I would have liked to be able to write something like: type Queue is new Queues.Set with null record overriding Is_Empty (Q : Queue) return Boolean; -- Not Ada! No doubt you have already found a solution for Is_Empty, but anyway here is what I would do: function Is_Empty (Q : Queue) return Boolean is begin return Queues.Is_Empty (Queues.Set (Q)); end Is_Empty; -- Niklas Holsti Tidorum Ltd niklas holsti tidorum fi . @ .