Ada 中动态数组的索引器和引用类型
Indexer and reference type for dynamic arrays in Ada
我有以下规格:
generic
type Value_Type is private;
package Containers.Arrays is
type Static_Array is array(Positive range <>) of Value_Type;
type Static_Array_Access is access all Static_Array;
type Dynamic_Array is tagged private;
function Length(Self : Dynamic_Array) return Natural with Inline;
function "&"(Left : Dynamic_Array; Right : Value_Type) return Dynamic_Array;
private
type Dynamic_Array is tagged record
Backing : Static_Array_Access;
end record with
Variable_Indexing => Variable_Indexer;
type Variable_Reference(Data : access Value_Type) is null record with
Implicit_Dereference => Data;
function Variable_Indexer(Self : Dynamic_Array; Index : Positive)
return Variable_Reference with Pre => Index <= Self.Length;
连同 Variable_Indexer 的实现如下:
function Variable_Indexer(Self : Dynamic_Array; Index : Positive)
return Variable_Reference is
begin
return Variable_Reference(Data => new Value_Type'(Self.Backing(Index)));
end Variable_Indexer;
我已经知道这里的问题了,但我仍然会给出我的测试代码并解释发生了什么。
DA : Dynamic_Array := 'a' & 'b' & 'c';
pragma Assert(DA.Length = 3);
pragma Assert(DA(1) = 'a');
pragma Assert(DA(2) = 'b');
pragma Assert(DA(3) = 'c');
目前一切顺利
DA(1) := 'A'; --Change to majiscule from miniscule
pragma Assert(DA(1) = 'A'); --fails
我知道这是因为 Variable_Indexer 没有引用 DA(1),但实际上在堆上分配了一个新变量,其值恰好是 DA(1) 恰好具有的值。我想我需要别名值和 return 对别名的访问。然而,我一直无法编译这样的东西,更不用说工作了。
感谢@ajb 的帮助,因为我完全忘记了为数组元素设置别名。
将Static_Array更改为:
type Static_Array is array(Positive range <>) of aliased Value_Type;
并将Variable_Indexer更改为:
function Variable_Indexer(Self : Dynamic_Array; Indexer : Positive) return Variable_Reference is
begin
return Variable_Reference'(Data => Self.Backing(Index)'Access);
end Variable_Indexer;
现在,它不再在堆上创建新值并返回指向该值的指针,而是 returns 指向数组中元素的指针;这是正确的行为。
我有以下规格:
generic
type Value_Type is private;
package Containers.Arrays is
type Static_Array is array(Positive range <>) of Value_Type;
type Static_Array_Access is access all Static_Array;
type Dynamic_Array is tagged private;
function Length(Self : Dynamic_Array) return Natural with Inline;
function "&"(Left : Dynamic_Array; Right : Value_Type) return Dynamic_Array;
private
type Dynamic_Array is tagged record
Backing : Static_Array_Access;
end record with
Variable_Indexing => Variable_Indexer;
type Variable_Reference(Data : access Value_Type) is null record with
Implicit_Dereference => Data;
function Variable_Indexer(Self : Dynamic_Array; Index : Positive)
return Variable_Reference with Pre => Index <= Self.Length;
连同 Variable_Indexer 的实现如下:
function Variable_Indexer(Self : Dynamic_Array; Index : Positive)
return Variable_Reference is
begin
return Variable_Reference(Data => new Value_Type'(Self.Backing(Index)));
end Variable_Indexer;
我已经知道这里的问题了,但我仍然会给出我的测试代码并解释发生了什么。
DA : Dynamic_Array := 'a' & 'b' & 'c';
pragma Assert(DA.Length = 3);
pragma Assert(DA(1) = 'a');
pragma Assert(DA(2) = 'b');
pragma Assert(DA(3) = 'c');
目前一切顺利
DA(1) := 'A'; --Change to majiscule from miniscule
pragma Assert(DA(1) = 'A'); --fails
我知道这是因为 Variable_Indexer 没有引用 DA(1),但实际上在堆上分配了一个新变量,其值恰好是 DA(1) 恰好具有的值。我想我需要别名值和 return 对别名的访问。然而,我一直无法编译这样的东西,更不用说工作了。
感谢@ajb 的帮助,因为我完全忘记了为数组元素设置别名。
将Static_Array更改为:
type Static_Array is array(Positive range <>) of aliased Value_Type;
并将Variable_Indexer更改为:
function Variable_Indexer(Self : Dynamic_Array; Indexer : Positive) return Variable_Reference is
begin
return Variable_Reference'(Data => Self.Backing(Index)'Access);
end Variable_Indexer;
现在,它不再在堆上创建新值并返回指向该值的指针,而是 returns 指向数组中元素的指针;这是正确的行为。