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: 103376,9e5d694241060c24 X-Google-Attributes: gid103376,public From: Paul Chardon Subject: Re: Tagged types and static dispatching Date: 1996/12/02 Message-ID: <32A312FE.41C67EA6@avions.aerospatiale.fr>#1/1 X-Deja-AN: 201913125 references: <32A2E972.28AF@masda.hv.se> to: Tobias Ritzau content-type: text/plain; charset=us-ascii mime-version: 1.0 newsgroups: comp.lang.ada x-mailer: Mozilla 3.0 (X11; I; SunOS 4.1.3_U1 sun4m) Date: 1996-12-02T00:00:00+00:00 List-Id: Tobias Ritzau wrote: > > Hi everyone! > > I have some trouble understanding some featers of Ada 95. I wrote a > small package with a linked list and a list iterator. Of course I wanted > the types to be tagged so that I could expand them later on. When I > compiled my package I got an error message saying: > operation can be displatching in only one type > The error was on the restart procedure below. > > package list is > > type List is tagged private; > type ListIt is tagged private; > > procedure insert(l : in out List; el : in T); > function length(l : in List) return Natural; > > procedure restart(li : in out ListIt; l : in List); > procedure next(li : in out ListIt); > function atend(li : in ListIt) return Boolean; > function item(li : in ListIt) return T; > > private > ... > > I removed the tagged keyword from the iterator and then everything > compiled ok. Then I reinserted the tagged word and replaced the > parameter types by ListIt'Class and List'Class and again everything > compiled ok. > If I have understood things correctly the Class attributes enables > dynamic binding and I don't want to use dynaimc binding. Why can't I use > two tagged types as parameters to a sub-program? What is the correct way > to do this? > > Thank you for helping me > > Tobias Ritzau Hello, When you are defining a tagged types and operations about this types, each operation must contain only one parameter of this type to be a primitive operation, that is to say an operation on which you can do dispatching. This parameter is called a CHOICE PARAMETER. This parameter is the basis of the dispatching which use the tag of the type to choose the correct operation to invoke. If you build an operation with two parammeters of the tagged type, the compiler won't be able to find which tag to use to construct the dispatching call. Another criteria will be need to select the good parameter tag. So such an operation is not a primitive operation of the tagged type, no dispatching for it and it won't be inherited. On the contrary what you can do (described in RM and ARM) is dispatching and redispatching which use primitive operations including parameter of another class wide type, and then the dispatching operation has got two class-wide type parameters. But I think read some examples on the rationale if you've got it, it is very well explained. I even give you an example from it. This example from the Rationale will perhaps help you to construct you list handler. package Doubly_Linked is type Node_Type is tagged limited private; type Node_Ptr is access all Node_Type'Class; -- define add/remove operations, -- assuming head of list is a single Node_Ptr procedure Add(Item: Node_Ptr; Head: in out Node_Ptr); -- add new node at head of list procedure Remove(Item: Node_Ptr; Head: in out Node_Ptr); -- remove node from list, update Head if necessary -- define functions to iterate forward or backward over list function Next(Item: Node_Ptr) return Node_Ptr; function Prev(Item: Node_Ptr) return Node_Ptr; private type Node_Type is tagged limited record Prev: Node_Ptr := null; Next: Node_Ptr := null; -- other components to be added by extension end record; end Doubly_Linked; with Ada.Unchecked_Deallocation; package body Doubly_Linked is -- define add/remove operations, -- assuming head of list is a single Node_Ptr procedure Add(Item: Node_Ptr; Head: in out Node_Ptr) is First : Node_Ptr := Head; begin if (Head /= null) then Head.Prev := Item; Head := Item; Head.Next := First; else Head := Item; Head.Prev := null; Head.Next := null; end if; end Add; -- add new node at head of list procedure Remove(Item: Node_Ptr; Head: in out Node_Ptr) is Current : Node_Ptr := Head; procedure Remove_Node is new Ada.Unchecked_Deallocation(Node_Type'Class,Node_Ptr); begin if (Item = Head) then Head := Item.Next; Current := Item; Remove_Node -- define functions to iterate forward or -- backward over list(Current); else loop exit when (Current = null); exit when (Current = Item); Current := Current.Next; end loop; if (Current /= null) then Current.Prev.Next := Item.Next; Remove_Node(Current); end if; end if; end Remove; function Next(Item: Node_Ptr) return Node_Ptr is begin return Item.Next; end Next; function Prev(Item: Node_Ptr) return Node_Ptr is begin return Item.Prev; end Prev; end Doubly_Linked; Hope it will help you, Paul.