Ada 202x (55日目) - 1月20日の電子会議の結果

1月20日に行われた電子会議の議事録が公開されました。

Interfaces.C.bool

追加されます。 C言語の _Bool に対応する型です。 宣言は type bool is new Boolean; type C_bool is new Boolean;_Bool 互換となるよう実装依存の内部表現が指定される形です。 Boolean からの派生ですので真偽値は TrueFalse を継承しています。

えっ、まだ規格に入ってなかったの?

35日目に追記しました。

Pre'Classからのabstract関数の呼び出し

abstract関数を Pre'Class の中で呼び出せるようになります。

package Pkg1 is
   type T is abstract tagged null record;
   function P (Object : T) return Boolean is abstract;
   procedure Do_Something (Object : in T) is abstract
      with Pre'Class => P (Object);
end Pkg1;

これまではabstract関数 P はここで使用できませんでした。

Ada 2012 Technical Corrigendum 1以前は Pre'Class の中での呼び出しは多態していたためエラーにはなりませんでした。 以降も明示的に P (T'Class (Object)) のように多態させれば可能ではありました。 ただし事前条件を多態させてしまいますと派生型の側で置換原則を守らないようにもできてしまいますので注意が必要です。

この T から派生してインスタンス化可能な型 D を作ってみます。

with Pkg1;
package Pkg2 is
   type D is new Pkg1.T with null record;
   overriding function P (Object : T) return Boolean is (True);
   overriding procedure Do_Something (Object : in T) is null;
     -- Pre'Class => P (Object)
end Pkg1;

DDo_Something の事前条件は Pkg2.P (Object) となります。 26日目で述べたように T がabstract型でなければ Pkg1.P (Pkg1.T (Object)) and Pkg2.P (Object) となりますが、abstract型は飛ばされますので Pkg2.P (Object) だけとなります。

これに伴い、このような事前条件を持つプリミティブはabstract型のclass-wide型からの多態呼び出しが禁止されました。 事前条件は多態しないからです。

declare
   Object : Pkg1.T'Class := Pkg2.D'(null record);
begin
   Pkg1.Do_Something (Object); -- error

勿論abstract型ではない Pkg2.D'Class 型からの多態呼び出しはできます。

pragma Pure/Preelaborate

pragma PurePreelaborate がobsolescentになります。

これに限らず同名のアスペクトが用意されたものはpragmaではなくアスペクトを使っていったほうが良いでしょう。

個人的にはpragmaの宣言から離して書ける利点も捨てがたいとは思っています。 pragma Inline 等のセマンティクスに影響を与えないものは離して書きたいです。

アスペクトの分類

型に付く各アスペクトについて、 Integer_LiteralSize 等は派生先で再定義可能、 Constant_Indexing 等は再定義不可能、 Stable_Properties 等は継承されない、 Put_ImageWrite 等は継承元の定義を使用する形で再構成される、みたいに派生先でどうなるかはまちまちでした。

整理のため3種類に分類されます。

  • implicitly composed

    直接は継承されませんが派生元の値を使って再構成されます。 Put_ImageReadWrite 等。

  • additive

    直接は継承されませんが動作は引き継がれます。 Default_Initial_ConditionStatic_PredicateType_Invariant'Class 等。

  • nonoverridable

    継承され再定義できません。 interface 間で衝突します。 Constant_IndexingInteger_Literal 等。

なんかどさくさでユーザー定義リテラルがnonoverridableに分類されて再び再定義不可能になっている気がします。 41日目47日目を修正しました。

定数の要件

幾つかの場所で定数かどうかの判定に「variable viewを持たないこと」が加えられます。 (variable viewは 20日目で説明した変更可能な定数を作るテクニックです。)

例えばグローバル定数にアクセスしているだけでは Global アスペクトに書く必要はありませんが、その定数がvariable viewを持っていると書く必要があります。

標準のストレージプール

標準のストレージプールを非同期に呼び出した場合に衝突は起こらないことが明記されます。 これまではブロッキングしないことだけが書かれていました。

その他文面等の修正

例によって文面等の修正が複数のAIで行われています。

関連AI