String 用规则约束Ada中的无界_字符串或将其子类型化?

String 用规则约束Ada中的无界_字符串或将其子类型化?,string,constraints,ada,String,Constraints,Ada,对Ada来说是新的,但到目前为止我很喜欢它。我可能是在以一种无趣的方式问这个问题,因为我只是在写一些有用的东西作为我的突袭,但这里是这样的: 我有一个使用无界字符串的系统,我想对它们应用一些规则,比如长度是否可以被n整除,或者它们可以包含哪些字符。是否有一种简洁的方法来进行验证,这样我就可以依靠类型系统进行验证?您可以要求类型系统检查分配给变量的值,以及动态谓词方面: with Ada.Strings.Unbounded; package UB_Preds is use Ada.Strin

对Ada来说是新的,但到目前为止我很喜欢它。我可能是在以一种无趣的方式问这个问题,因为我只是在写一些有用的东西作为我的突袭,但这里是这样的:


我有一个使用
无界字符串的系统,我想对它们应用一些规则,比如长度是否可以被
n
整除,或者它们可以包含哪些字符。是否有一种简洁的方法来进行验证,这样我就可以依靠类型系统进行验证?

您可以要求类型系统检查分配给变量的值,以及动态谓词方面:

with Ada.Strings.Unbounded;
package UB_Preds
is
   use Ada.Strings.Unbounded;

   subtype Even_Length_String is Unbounded_String
   with Dynamic_Predicate => Length(Even_Length_String) mod 2 = 0;

   subtype Lower_Case_String is Unbounded_String
   with Dynamic_Predicate =>
      (for all C of To_String(Lower_Case_String) => C in 'a' .. 'z');

end UB_Preds;
用法示例:如果在启用断言检查的情况下编译(-gnata for GNAT),这些声明将引发Assert_Failure,因为指定的值使子类型的谓词失败:

Odd : UB_Preds.Even_Length_String := To_Unbounded_String ("ABC");
UC : UB_Preds.Lower_Case_String := To_Unbounded_String ("aBc");
第一个有三个字符,因此长度mod 2/=0,而第二个有一个大写字符

通常,断言检查的启用/禁用由pragma assertion_策略控制。GNAT的默认设置是忽略断言,但是-gnata启用它们


(当然,如果您使用7位ASCII以外的任何字符集,您应该使用Ada.Characters.Handling来测试小写/大写,而不是上面示例使用的简单范围。)

我已尝试使用
pragma assertion\u策略启用断言检查(检查)
在定义类型的包内和项目内无效。到目前为止,我让它工作的唯一方法是使用
-gnata
调用gprbuild。将
-gnata
放在Compiler.Default\u Switches指令中不会执行任何操作。我做错了什么?更新,我也试着把
pragma断言\u策略(检查)位于定义包含自定义子类型和nothing.Hm的包的文件顶部。我以前没有用pragma进行测试,但现在我用了,我看到了与您报告的相同的行为。我能说的只是“有趣”,还有一些事情要和AdaCore讨论。我认为RM在这一点上是明确的。我必须将
-gnata
选项添加到库的
*.gpr
*.gpr
中,对于使用库的项目,pragma似乎没有效果。非常令人沮丧,因为不必要求库的用户更改项目配置就可以了。