Gem #11: Limited Types in Ada 2005 — Constructor Functions Part 2
by Bob Duff —AdaCore
Let's get started…
We've earlier seen examples of constructor functions for limited types similar to this:
package P is type T (<>) is limited private; function Make_T (Name : String) return T; -- constructor function private type T is new Limited_Controlled with record … end record; end P; package body P is function Make_T (Name : String) return T is begin return (Name => To_Unbounded_String (Name), others => <>); end Make_T; end P; function Make_Rumplestiltskin return T is begin return Make_T (Name => “Rumplestiltskin”); end Make_Rumplestiltskin;
It is useful to consider the various contexts in which these functions may be called. We've already seen things like:
Rumplestiltskin_Is_My_Name : T := Make_Rumplestiltskin;
in which case the limited object is built directly in a standalone object. This object will be finalized whenever the surrounding scope is left.
We can also do:
procedure Do_Something (X : T); Do_Something (X => Make_Rumplestiltskin);
Here, the result of the function is built directly in the formal parameter X of Do_Something. X will be finalized as soon as we return from Do_Something.
We can allocate initialized objects on the heap:
type T_Ref is access all T; Global : T_Ref; procedure Heap_Alloc is Local : T_Ref; begin Local := new T'(Make_Rumplestiltskin); if … then Global := Local; end if; end Heap_Alloc;
The result of the function is built directly in the heap-allocated object, which will be finalized when the scope of T_Ref is left (long after Heap_Alloc returns).
We can create another limited type with a component of type T, and use an aggregate:
type Outer_Type is limited record This : T; That : T; end record; Outer_Obj : Outer_Type := (This => Make_Rumplestiltskin, That => Make_T (Name => “”));
As usual, the function results are built in place, directly in Outer_Obj.This and Outer_Obj.That, with no copying involved.
The one case where we _cannot_ call such constructor functions is in an assignment statement:
Rumplestiltskin_Is_My_Name := Make_T(Name => ""); -- Illegal!
which is illegal because assignment statements involve copying. Likewise, we can't copy a limited object into some other object:
Other : T := Rumplestiltskin_Is_My_Name; -- Illegal!