Reputation: 251
According to AI05-213, generics can now be instantiated with incomplete types. I would like to use this to build opaque containers: several packages define private types and matching containers. However, I would like the containers to derive from a common Containers.Container type that would provide some simple subprograms (e.g. Clear, Is_Empty, Iterate). For the latter, the type of elements to be stored in the container is needed, so package Containers has to be generic.
I couldn't get my code to compile, so I've experimented a bit. It seems that I can use a tagged type, but not a class-wide type, nor a child of a tagged type.
Why is this so? Any idea how to implement a simple container abstraction that works with private elements, and with various concrete containers (e.g. Map, Linked List, Set)?
with Containers;
package Actual is
type Element is tagged private;
type Sub_Element is new Element with private;
package List is new Containers (Element_Type => Element'class); --error
package Another is new Containers (Element_Type => Element); --ok
package Still_Another is new Containers (Element_Type => Sub_Element); --error
private
type Element is tagged null record;
type Sub_Element is new Element with null record;
end Actual;
generic
type Element_Type (<>) is tagged;
package Containers is
type Container is abstract tagged null record;
end Containers;
Upvotes: 2
Views: 858
Reputation: 2715
Moving the Element
type to another package changes the whole issue, since there is then no longer an issue with a premature use of type with private component. It might be a compiler error (and the current Pro version still shows the two errors), but I am not so sure.
In practice, though, using incomplete types like you do is unlikely to be very useful I think. There is basically nothing you can do about the Element_Type
in the containers package, since you know exactly nothing about it except that it is tagged. You can't store such an element (which is indefinite).
Using dynamic dispatching is also pretty bad for performance. I have recently spent a lot of time measuring things, and I recommend that you do early in your design as well. You will see that the cost of the dynamic dispatching is pretty costly. My own experience is that it is best to use generics for that approach. If I may be allowed a shameless plug, you might find a recent blog post interesting if you are designing containers: http://blog.adacore.com/traits-based-containers
Upvotes: 2