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.

有帮助吗?

解决方案

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;
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top