【问题标题】:In Ada, how could I make subtype of records?在 Ada 中,我如何制作记录的子类型?
【发布时间】:2013-11-02 15:40:39
【问题描述】:

如果我有这样的记录类型:

  type ABC is record
       A : Integer;
       B : Integer;
  end record;

如何使用两个指定范围的整数类型创建 ABC 的子类型?

【问题讨论】:

  • 你不知道。子类型适用于枚举、浮点数、整数等,但不适用于记录。如果您提供有关您的问题的更多信息,我们可能会提供更多帮助...
  • subtype XYZ is ABC; 是合法的,但不是 OP 要求的。

标签: record ada subtype


【解决方案1】:

虽然不回答您的问题本身(正如 NWS 所说,您不能那样做),但如果 A 和 B 不是整数,而是数组,您可以执行以下操作:

package Record_Subtypes is

   type Int_Data is array (Integer range <>) of Integer;

   type ABC (X_Min, X_Max, Y_Min, Y_Max : Integer) is record
      A : Int_Data (X_Min .. X_Max);
      B : Int_Data (Y_Min .. Y_Max);
   end record;

   subtype ABC_4_4 is ABC(X_Min => 1, X_Max => 4,
                          Y_Min => 1, Y_Max => 4);

   subtype ABC_1_7_3_12 is ABC (X_Min => 1, X_Max => 7,
                                Y_Min => 3, Y_Max => 12);
end Record_Subtypes;

然后,A 和 B 记录字段使用记录鉴别符提供的索引子类型。

这是我不时使用的一个好技巧,在从接口(例如套接字)读取可变长度字符串时很有用,其中要读取的字节数是通过固定大小的标头提供的;或者对于具有枚举判别式的变体记录,我可以将记录子类型化为特定变体。

【讨论】:

    【解决方案2】:

    你也可以使用泛型,像这样:

    generic
       type Number is range <>;
    package Int_Record is
       type ABC is record
          A, B : Number;
       end record;
    end Int_Record;
    

    如果您希望 A 和 B 的范围不同,则必须使用两个通用参数。

    用法如下:

    procedure Foo is
       subtype My_Int is Integer range 1 .. 3;
       package My_Int_Record is new Int_Record (Number => My_Int);
       X : My_Int_Record.ABC;
    begin
       X.A := 2; -- okay
       X.B := 4; -- error!
    end Foo;
    

    【讨论】:

      【解决方案3】:

      Ada 2012 中,我们现在有Dynamic_Predicate,我们可以使用它来施加子类型限制,如下所示:

      type ABC is record
          A : Integer;
          B : Integer;
        end record;
      
      subtype XYZ is ABC
        with dynamic_predicate => 
        ((XYZ.A in Positive) and
         (XYZ.B not in Positive)) or else raise Constraint_Error;
      

      【讨论】:

      • (a) 我想你的意思是or else raise Constraint_Error! (b) 在 RM 中的哪个位置允许这作为方面定义?我看到 GNAT GPL 2013 允许它(但不是 FSF GCC 4.8.0),我可以看到它在这里有意义。
      • 在 GNAT GPL 2013 中,使用 or raise Constraint_Error 构造意味着在声明行报告异常,尽管回溯显示使用失败。如果你忽略它,Assert_Error 会在使用失败时报告,这会更有帮助。
      • 是的,你说得对,它应该是or else raise。我尝试在 LRM 中查找构造,但没有找到。 (我认为我是在 comp.lang.ada 上从 Randy 那里了解到的。)
      【解决方案4】:

      给定:

      type ABC is record
         A : Integer;
         B : Integer;
      end record;
      

      你可以使用:

      type XYZ is record
         A : Positive;  -- A is subtype of ABC.A
         B : Natural;   -- B is subtype of ABC.B
      end record;
      
        function convert(Input: ABC) return XYZ is
        begin
           return Result : XYZ:= ( A => Input.A, B => Input.B );
        -- Put your exception handling here.
        end convert;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-12-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多