gpt4 book ai didi

pointers - Ada:如何访问 Vector 元素?

转载 作者:行者123 更新时间:2023-12-05 08:37:13 26 4
gpt4 key购买 nike

我有一些东西,我特意想在堆上分配并“通过引用”访问它们:

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Containers.Indefinite_Hashed_Maps;
with Ada.Containers; use Ada.Containers;

procedure Main is

type Thing_Key is new Integer;

type Thing is record
Key : Thing_Key;
Data : Integer;
end record;

type Thing_Access is access all Thing;

function Image (T : Thing) return String is
(T.Key'Image & '(' & T.Data'Image & ')');

function "=" (A, B : Thing) return Boolean is
(A.Key = B.Key);

function Thing_Hash (K : Thing_Key) return Hash_Type is
(Hash_Type (K));

package Thing_Map is new
Ada.Containers.Indefinite_Hashed_Maps
(Key_Type => Thing_Key,
Element_Type => Thing,
Hash => Thing_Hash,
Equivalent_Keys => "=");
use Thing_Map;

Map : Thing_Map.Map;
C : Cursor;
P : Thing_Access;
begin
P := new Thing '(Key => 1, Data => 2); -- on the heap

Map.Insert (P.Key, P.all);
Put_Line (Image (P.all)); -- '1( 2)', as expected

P.Data := 99;
Put_Line (Image (P.all)); -- '1( 99)', as expected

C := Map.Find (1); -- Get cursor to thing

-- Set P to point at the thing at the cursor?

-- Following lines don't compile
P := Map (C)'Access; -- access-to-variable designates constant
P := Map (C).Reference; -- undefined selector "Reference" for overloaded prefix
P := Map (C).Get_Element_Access; -- undefined selector "Get_Element_Access" for overloaded prefix
P := Map.Reference (C); -- no visible interpretation of "Reference" matches expected type "Thing_Access"
end Main;

从游标获取指针的语法是什么?

最佳答案

我假设您只想将元素存储在堆上,以便通过引用访问它们以进行操作。但是,使用 Ada 容器时不需要这样做。所有容器都有一些通过引用访问元素的方式(通过一些 Constant_ReferenceReference 函数,通常由于 Variable_Indexing 而被省略)在容器类型上定义的方面;例如,参见 Ada 2012 基本原理中的 section 6.3 和/或@Timur Samkharadze 的回答)。

如果您想将键存储为元素的一部分,那么我认为使用散列集可能更合适(参见 RM A.18.7RM A.18.8learn.adacore.com )。可以通过函数 Reference_Preserving_Key 通过引用访问散列集中的元素(另请参阅 RM 96.10 (3) )。

下面是两个示例:第一个示例展示了如何更新 Hashed_Map 中的元素,第二个示例展示了如何更新 Hashed_Set 中的元素,两者都使用一把 key :

ma​​in.adb(Hashed_Map)

with Ada.Text_IO;    use Ada.Text_IO;
with Ada.Containers; use Ada.Containers;
with Ada.Containers.Hashed_Maps;

procedure Main is

type Thing_Key is new Integer;

type Thing is record
Key : Thing_Key;
Data : Integer;
end record;

function Image (T : Thing) return String is
("Key = " & T.Key'Image & ", Value = " & T.Data'Image);

function Hash (K : Thing_Key) return Hash_Type is (Hash_Type (K));

package Things is new Ada.Containers.Hashed_Maps
(Key_Type => Thing_Key,
Element_Type => Thing,
Hash => Hash,
Equivalent_Keys => "=");

Map : Things.Map;

begin

-- Inserting 4 elements. Note that the key is now stored twice: once in
-- the map's key index (its hash, to be more precise), and once in the item
-- itself (unhashed). You must now ensure that the key value in the
-- element does not accidentally get out-of-sync with the hashed key in the
-- map's key index (e.g. when you update the stored element). Of course,
-- you could also you just omit the key in the element itself if possible
-- given your use-case.

Map.Insert (Key => 1, New_Item => (Key => 1, Data => 10));
Map.Insert (Key => 2, New_Item => (Key => 2, Data => 20));
Map.Insert (Key => 3, New_Item => (Key => 3, Data => 30));
Map.Insert (Key => 4, New_Item => (Key => 4, Data => 40));

for T of Map loop
Put_Line (Image (T));
end loop;
New_Line;

-- Update element with key 3.
--
-- Note that the following expressions are all equivalent:
--
-- Map.Reference (3).Element.all.Data := 300; -- Original expression
-- Map.Reference (3).Element.Data := 300; -- Omit "all" due to implicit dereferencing of access types in Ada.
-- Map.Reference (3).Data := 300; -- Omit "Element" due to the "Implicit_Dereferencing" aspect on the "Hashed_Maps.Reference_Type".
-- Map (3).Data := 300; -- Omit "Reference" due to the "Variable_Indexing" aspect on the "Hashed_Maps.Map" type.
--
Map (3).Data := 300;

-- Example if you really need a pointer to element with key 3.
declare

type Thing_Access is not null access all Thing;
type Thing_Constant_Access is not null access constant Thing;

-- Element is mutable via P , i.e. P.Data := 301 (OK)
-- Element is not mutable via CP, i.e. CP.Data := 302 (Error)

P : Thing_Access := Map.Reference (3).Element;
CP : Thing_Constant_Access := Map.Constant_Reference (3).Element;

begin
null;
end;

for T of Map loop
Put_Line (Image (T));
end loop;
New_Line;

end Main;

ma​​in.adb(Hashed_Set)

with Ada.Text_IO;    use Ada.Text_IO;
with Ada.Containers; use Ada.Containers;
with Ada.Containers.Hashed_Sets;

procedure Main is

type Thing_Key is new Integer;

type Thing is record
Key : Thing_Key;
Data : Integer;
end record;

function Image (T : Thing) return String is
("Key = " & T.Key'Image & ", Value = " & T.Data'Image);

function Key (T : Thing) return Thing_Key is (T.Key);
function Hash (T : Thing) return Hash_Type is (Hash_Type (T.Key));
function Hash (K : Thing_Key) return Hash_Type is (Hash_Type (K));

package Things is new Ada.Containers.Hashed_Sets
(Element_Type => Thing,
Hash => Hash,
Equivalent_Elements => "=");

package Things_Keys is new Things.Generic_Keys
(Key_Type => Thing_Key,
Key => Key,
Hash => Hash,
Equivalent_Keys => "=");

Set : Things.Set;

begin

-- Inserting 4 elements. Note that the key is stored only in the element.

Set.Insert ((Key => 1, Data => 10));
Set.Insert ((Key => 2, Data => 20));
Set.Insert ((Key => 3, Data => 30));
Set.Insert ((Key => 4, Data => 40));

for T of Set loop
Put_Line (Image (T));
end loop;
New_Line;

-- Update the element. See also RM 96.10 (3). Opposed to most other
-- containers, you cannot omit "Reference_Preserving_Key" as the "Set" type
-- does not have a "Variable_Indexing" aspect specifying "Reference_Preserving_Key".
-- Hence, you need write it out explicitly.

Things_Keys.Reference_Preserving_Key (Set, 3).Data := 300;

-- Example if you really need a pointer to element with key 3.
declare

type Thing_Access is not null access all Thing;
type Thing_Constant_Access is not null access constant Thing;

-- Element is mutable via P , i.e. P.Data := 301 (OK)
-- Element is not mutable via CP, i.e. CP.Data := 302 (Error)

P : Thing_Access := Things_Keys.Reference_Preserving_Key (Set, 3).Element;
CP : Thing_Constant_Access := Things_Keys.Constant_Reference (Set, 3).Element;

begin
null;
end;

for T of Set loop
Put_Line (Image (T));
end loop;
New_Line;

end Main;

输出(两者相同)

Key =  1, Value =  10
Key = 2, Value = 20
Key = 3, Value = 30
Key = 4, Value = 40

Key = 1, Value = 10
Key = 2, Value = 20
Key = 3, Value = 300
Key = 4, Value = 40

关于pointers - Ada:如何访问 Vector 元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66291973/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com