|
Author: Bob Duff, AdaCore
Abstract: Ada Gem #11 — We show here how limited constructor functions can be used in various contexts to build new limited objects in place.
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!
Posted
in Ada / Ada 2005, Development Log, Devt log - Gem of the Week
If you have an idea for a Gem you would like to contribute please feel free to contact us at: gems@adacore.com