Non trivial exemples of use of generic dispatching constructors

Hi, I have read about generic dispatching constructors, from several books, but I have yet to understand what makes the generic function special or “magical”. And it relies on constructors with controlling results, which as far as I read aren’t very appreciated. Where can I find code making heavy uses of such things ?

Do you mean the factory constructor stuff? I doubt many people use it.

Yes, the factory constructor. Well the use statistics aren’t exactly included in manuals, but I’ve seen it in the Barnes and Ben-Ari’s Ada for Software Engineers, 2e edition with Ada 2005, and they made it look pretty cool. I understand it is magical because without it is impossible to automatically match a tag with the corresponding primitive, you would need to make your own dispatching table.

It dispoatches on the 'tag doesn’t it?

Generic_Dispatching_Constructor creates an object from its type tag. It is generic so that you could pass parameters to it.

Here is an example of use in a middleware:

function New_Value is
   new Generic_Dispatching_Constructor
       (  Register_Value,
          Register_Value_Factory_Interface'Class,
          New_Value
       );

It creates a new value of a middleware register. Registers are process variables of different types which can be read written from/to the hardware which changes can be monitored, logged etc.

Register_Value is the base type of all register values. It is abstract and contains shared properties like timestamp, error status etc.

Register_Value_Factory_Interface is the interface used to provide the parameters for the constructor. There are many instances for each class of registers, e.g. integer factory, string factory etc.

New_Value named same as the instance, don’t be confused, they nicely overload. This is a primitive operation that each concrete register value type overrides, e.g. Float_Value, a value of a Float-valued register:

function New_Value
         (  Factory : not null access
                      Register_Value_Factory_Interface'Class
         )  return Float_Value;

When the tag indicates Float_Value then New_Value is called to create it. Factory provides necessary parameters.

Sort of. Generic_Dispatching_Constructor is limited to the same process. If you transfer serialized object over the network or load things from a DLL you would not use Generic_Dispatching_Constructor even though there is external tag representation in Ada.Tags. Instead of that you would have some registration service that would map your own portable representation of the tag to a constructing function. This is kind of a dispatching table, though there is nothing magical about it.

P.S. If you remember discussion about covariance. Note that New_Value is covariant and thus the compiler will force you to override it. Which is the only safe choice.