Ada中动态数组的索引器和引用类型

时间:2015-05-24 23:58:03

标签: indexing ada dynamic-arrays reference-type

我有以下规格:

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)恰好具有这个值。我想我需要为值设置别名并返回对别名的访问权限。但是,我一直无法编写这样的东西,更不用说工作了。

1 个答案:

答案 0 :(得分:3)

感谢@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;

现在,它不是在堆上创建新值,而是返回指向它的指针,而是返回指向数组中元素的指针;这是正确的行为。