You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否声明同时适配受限数组与非受限数组的泛型函数?

Ada泛型数组查找函数适配受限与非受限数组的解决方案

问题背景

现有一个用于查找数组元素索引的Ada泛型函数,定义如下:

generic
   type T is private;
   type T_index is (<>);
   type T_array is array(T_index range <>) of T;
function FindIndexGeneric(array: T_array; element: T; elementFound: out Boolean) return T_index;

该函数实例化为非受限数组(如String)时可正常运行:

function FindIndexString is new FindIndexGeneric
  (T=>Character, T_index=>Positive, T_array=>String);

但实例化为固定长度的受限数组时会报错:

type userIDIndex is Integer range 1..6;
type userID is array(userIDIndex) of Character;
function FindIndexUserID is new FindIndexGeneric
  (T=>Character, T_index=>userIDIndex, T_array=>userID);
-- 错误提示:expect unconstrained array in instantiation of "T_array"

若将泛型中的数组声明改为type T_array is array(T_index) of T;,则可适配受限数组,但无法再实例化非受限数组。由于核心查找逻辑一致,无需编写多个泛型版本,需找到同时支持两种数组类型的方案。

解决方案

方案1:基于抽象数组操作的泛型定义

通过将数组类型声明为私有类型,并添加获取元素、索引范围的泛型回调函数,实现对任意数组类型(受限/非受限)的适配。

泛型函数定义

generic
   type T is private;
   type T_Index is (<>);
   type T_Array is private;
   -- 获取数组指定索引的元素
   with function Element(Arr : T_Array; Idx : T_Index) return T;
   -- 获取数组的起始索引
   with function First(Arr : T_Array) return T_Index;
   -- 获取数组的结束索引
   with function Last(Arr : T_Array) return T_Index;
function FindIndexGeneric(Arr : T_Array; Target : T; Found : out Boolean) return T_Index;

泛型函数实现

function FindIndexGeneric(Arr : T_Array; Target : T; Found : out Boolean) return T_Index is
begin
   Found := False;
   for Idx in First(Arr)..Last(Arr) loop
      if Element(Arr, Idx) = Target then
         Found := True;
         return Idx;
      end if;
   end loop;
   -- 未找到时返回起始索引,可根据需求调整(如抛出异常)
   return First(Arr);
end FindIndexGeneric;

实例化示例

  • 非受限数组String实例化:
function FindIndexString is new FindIndexGeneric
  (T => Character,
   T_Index => Positive,
   T_Array => String,
   Element => String.Element,
   First => String'First,
   Last => String'Last);
  • 受限数组userID实例化(Ada 2012及以上可用表达式函数简化):
type userIDIndex is Integer range 1..6;
type userID is array(userIDIndex) of Character;

function FindIndexUserID is new FindIndexGeneric
  (T => Character,
   T_Index => userIDIndex,
   T_Array => userID,
   Element => (function (Arr : userID; Idx : userIDIndex) return Character is (Arr(Idx))),
   First => (function (Arr : userID) return userIDIndex is (Arr'First)),
   Last => (function (Arr : userID) return userIDIndex is (Arr'Last)));

方案2:利用非受限数组基类型适配受限数组

对于受限数组,可直接以其对应的非受限数组基类型作为泛型的T_array参数,受限数组作为子类型可隐式转换为非受限数组类型,无需修改原泛型函数定义。

实例化示例

type userIDIndex is Integer range 1..6;
type userID is array(userIDIndex) of Character;

-- 以非受限数组基类型作为T_array参数
function FindIndexUserID is new FindIndexGeneric
  (T => Character,
   T_Index => userIDIndex,
   T_Array => array(userIDIndex range <>) of Character);

-- 调用时可直接传入userID类型变量
declare
   ID : userID := "123456";
   Found : Boolean;
   Idx : userIDIndex;
begin
   Idx := FindIndexUserID(ID, '3', Found);
end;

总结

方案1通过抽象数组操作实现了最大的灵活性,可适配任意自定义数组类型;方案2无需修改原泛型函数,仅需调整实例化时的数组类型参数,实现成本更低,适合已有泛型函数的场景。

内容的提问来源于stack exchange,提问作者Adi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 12:45:25