Operation can be dispatching in only one type
Asked Answered
H

1

5

I have a record and wanted some accessor function for it.

package Some_Package is                                                             

   type A is tagged record                                                          
      First_Field  : Integer;                                                       
      Second_Field : Character;                                                     
   end record;                                                                      

   type B is private;                                                               

   function Some_A (Some_B : B) return A;                                           

private                                                                             

   type B is tagged record                                                          
      Some_A : A;                                                                   
   end record;                                                                      

end Some_Package;

And here's what GNAT gives me:

some_package.ads:10:13: operation can be dispatching in only one type

This error is somewhat cryptic for Ada newbie and I'd appreciate some explanation what I did wrong and how to do it correctly.

Hippel answered 25/7, 2012 at 9:14 Comment(0)
B
12

This is because of a specific rule in the ARM; there are two tagged types involved (B privately), and in Ada a subprogram can dispatch on one of its parameters or on the function result (actually, it would be OK if all the parameters and the result were the same tagged type). I think this is a consequence of Ada’s single-inheritance design.

Do you actually need A to be tagged? (I expect this is a cut-down version of the actual problem code).

If both A and B need to be tagged, the canonical solution for function Some_A is to make one of its parameters/results class-wide (a class-wide parameter isn’t dispatching):

function Some_A (Some_B : B'Class) return A;

or

function Some_A (Some_B : B) return A'Class;

depending on which makes more sense from the application point of view; guessing the second, you can then say

The_A : A’Class := Some_A (Some_B => The_B);

By the way, it would be clearer to readers, and wouldn’t lose much encapsulation, if you said

type B is tagged private;
Bamby answered 25/7, 2012 at 11:21 Comment(4)
Great answer. There's only one thing I'd like to see clarified - what exactly 'to dispatch' means in this context? I tried some googling but it is used differently for different things in Ada context.Hippel
@Mikolaj: Check out the chapter on Object Orientation in the Ada Wikibook, dispatching in particular.Garris
@MarcC, I copied your link into the answer. Thanks.Bamby
See also this about the dispatch table Dispatch table. I think (corrections welcome!) that your some_package code would have required 2 tables (Not one - Single inheritance) and therefore the code could not dynamically determine which table to use to dispatch on.Dander

© 2022 - 2024 — McMap. All rights reserved.