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=unavailable autolearn_force=no version=3.4.4 Path: eternal-september.org!reader01.eternal-september.org!reader02.eternal-september.org!news.eternal-september.org!mx02.eternal-september.org!.POSTED!not-for-mail From: "Jeffrey R. Carter" Newsgroups: comp.lang.ada Subject: Re: operation can be dispatching in only one type Date: Mon, 23 Nov 2015 10:40:52 -0700 Organization: Also freenews.netfront.net; news.tornevall.net; news.eternal-september.org Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit Injection-Date: Mon, 23 Nov 2015 17:38:33 -0000 (UTC) Injection-Info: mx02.eternal-september.org; posting-host="caa759af2a9c666aec02942f6fe5abd6"; logging-data="29024"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+cvaREXWtRVhUMPyd5taeXLnjp2R1AK1o=" User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.3.0 In-Reply-To: Cancel-Lock: sha1:lPXi4zzuOB/9SlDjgIogaH2puzk= X-Enigmail-Draft-Status: N1110 Xref: news.eternal-september.org comp.lang.ada:28510 Date: 2015-11-23T10:40:52-07:00 List-Id: On 11/23/2015 03:23 AM, Serge Robyns wrote: > > I'm facing an issue with Ada when it comes to use an operation on two tagged types. It isn't a road blocker and I've found my way around and are not using tagged types for these anymore. I've now a function that computes the total balance every time. Another option is to pass the id and then search the map. > > type T_Balance is tagged record > Id : T_Balance_Id; > Name : T_Balance_Name; > Balance : T_Amount; > end record; > > package Balance_Map is new > Ada.Containers.Ordered_Maps (Key_Type => T_Balance_Id, > Element_Type => T_Balance); > > type T_Account is tagged record > Name : T_Account_Name; > Total_Balance : T_Money; > Balances : Balance_Map.Map; > end record; > > And I want to have an operation increasing a balance and the total in the account. > The following declaration is refused: > > procedure Update_Balance > (Self : in out T_Account; > AB : in out T_Balance; > Amount : in T_Money); > > My hope was that it gets dispatched to the right operation on Self which in turns will call the right operation on AB. But the compiler seems not to agree. Ada has only single dispatch, so an operation can only be a primitive operation of a single tagged type (the "controlling" type). In Ada, neither the parameter name (Self) nor the position of the parameter in the parameter list determine the type for which an operation of a tagged type dispatches. Instead, it dispatches on the parameter of a tagged type for which it is a primitive operation. [A primitive operation is declared in the same declarative part as the type (usually a pkg spec).] Since here you have 2 tagged types in the same declarative part, this operation is primitive for both, which violates the Ada rule. Note that in the standard containers, type Cursor is not tagged for precisely this reason: They need operations that take both a container and a cursor as parameters. The standard approach to this is to put each tagged type in a separate pkg: package Balances is type Balance_Info is ... procedure Op (Balance : in out Balance_Info); end Balances; with Balances; package Accounts is type Account_Info is ... procedure Op (Account : in out Account_Info; Balance : in out Balances.Balance_Info); end Accounts; Another approach is to make one parameter classwide; then it is primitive for only one tagged type: procedure Op (Account : in out Account_Info; Balance : in out Balance_Info'Class); A third possibility is to make the operation non-primitive by putting it in a different declarative part: package Non_Primitive is procedure Op (Account : in out Account_Info; Balance : in out Balance_Info); end Non_Primitive; A fourth approach is to make one of the types non-tagged, as with Cursor in the containers. A fifth approach is to make all types non-tagged. This approach causes the fewest problems. > class account { > public: > account_id id; > account_name name; > money total_balance; > balance_list balances; > > account(); > virtual ~account(); > > void update_balance (account_balance& ab, money amount); This is a primitive operation of type account (to use the Ada terminology) because it occurs in account's class structure. Ada has a somewhat idiosyncratic syntax for programming by extension. > }; -- Jeff Carter "Now look, Col. Batguano, if that really is your name." Dr. Strangelove 31