使用过程 class-wide out 参数作为函数 return 值
Using procedure class-wide out argument as function return value
type T is abstract tagged null record;
type T1 is new T with null record;
procedure Get_Value (Value : out T'Class) is
T1_Value : T1 := (null record);
begin
Value := T'Class (T1_Value);
end;
function Result return T'Class is
T_Class_Value : T'Class; -- Initialization required
begin
Get_Value (T_Class_Value);
return T_Class_Value;
end Result;
在此代码中 T_Class_Value 需要初始化。如何从 Get_Value 参数初始化 T_Class_Value?
with Ada.Text_Io; use ADa.Text_IO;
procedure Main is
type T is abstract tagged null record;
type T1 is new T with null record;
function Result return T1'Class is
T1_Value : t1 := (Null record);
begin
return T1'Class(T1_Value);
end Result;
T1_Class : T1'Class := Result;
begin
Put_Line("It works");
end Main;
这很丑陋,但可以编译:
subtype T_Class is T'Class;
type T_Class_Access is access T_Class;
procedure Get_Value (Value_P : out T_Class_Access) is
T1_Value : T1 := (null record);
T_Class_Value : T_Class := T'Class (T1_Value);
begin
Value_P := new T_Class'(T_Class_Value);
end;
function Result return T'Class is
T_Class_P : T_Class_Access;
begin
Get_Value (T_Class_P);
return Result : T'Class := T_Class_P.all do
Free (T_Class_P);
end return;
end Result;
我不知道这个想法有多好,但到目前为止我已经确定了这个解决方案:
type T is abstract tagged null record;
type T1 is new T with null record;
type T_Null_Stub is new T with null record;
T_Null : constant T_Null_Stub := (null record);
procedure Get_Value (Value : out T'Class) is
T1_Value : T1 := (null record);
begin
Value := T'Class (T1_Value);
end;
function Result return T'Class is
T_Class_Value : T'Class := T_Null;
begin
Get_Value (T_Class_Value);
return T_Class_Value;
end Result;
希望有更优雅的解决方案。
这里我们使用Indefinite_Holders:
package T_Class_Holders is new Ada.Containers.Indefinite_Holders (T'Class);
procedure Get_Value (Value : out T_Class_Holders.Holder) is
T1_Value : constant T1 := (Z => 42);
begin
Value.Replace_Element (T'Class (T1_Value));
end;
function Result return T'Class is
T_Class_H : T_Class_Holders.Holder;
begin
Get_Value (T_Class_H);
return T_Class_H.Element;
end Result;
(我用了
type T1 is new T with record
Z : Integer;
end record;
所以我可以检查是否返回了正确的值)
type T is abstract tagged null record;
type T1 is new T with null record;
procedure Get_Value (Value : out T'Class) is
T1_Value : T1 := (null record);
begin
Value := T'Class (T1_Value);
end;
function Result return T'Class is
T_Class_Value : T'Class; -- Initialization required
begin
Get_Value (T_Class_Value);
return T_Class_Value;
end Result;
在此代码中 T_Class_Value 需要初始化。如何从 Get_Value 参数初始化 T_Class_Value?
with Ada.Text_Io; use ADa.Text_IO;
procedure Main is
type T is abstract tagged null record;
type T1 is new T with null record;
function Result return T1'Class is
T1_Value : t1 := (Null record);
begin
return T1'Class(T1_Value);
end Result;
T1_Class : T1'Class := Result;
begin
Put_Line("It works");
end Main;
这很丑陋,但可以编译:
subtype T_Class is T'Class;
type T_Class_Access is access T_Class;
procedure Get_Value (Value_P : out T_Class_Access) is
T1_Value : T1 := (null record);
T_Class_Value : T_Class := T'Class (T1_Value);
begin
Value_P := new T_Class'(T_Class_Value);
end;
function Result return T'Class is
T_Class_P : T_Class_Access;
begin
Get_Value (T_Class_P);
return Result : T'Class := T_Class_P.all do
Free (T_Class_P);
end return;
end Result;
我不知道这个想法有多好,但到目前为止我已经确定了这个解决方案:
type T is abstract tagged null record;
type T1 is new T with null record;
type T_Null_Stub is new T with null record;
T_Null : constant T_Null_Stub := (null record);
procedure Get_Value (Value : out T'Class) is
T1_Value : T1 := (null record);
begin
Value := T'Class (T1_Value);
end;
function Result return T'Class is
T_Class_Value : T'Class := T_Null;
begin
Get_Value (T_Class_Value);
return T_Class_Value;
end Result;
希望有更优雅的解决方案。
这里我们使用Indefinite_Holders:
package T_Class_Holders is new Ada.Containers.Indefinite_Holders (T'Class);
procedure Get_Value (Value : out T_Class_Holders.Holder) is
T1_Value : constant T1 := (Z => 42);
begin
Value.Replace_Element (T'Class (T1_Value));
end;
function Result return T'Class is
T_Class_H : T_Class_Holders.Holder;
begin
Get_Value (T_Class_H);
return T_Class_H.Element;
end Result;
(我用了
type T1 is new T with record
Z : Integer;
end record;
所以我可以检查是否返回了正确的值)