Ada 202x (43日目) - その他のgenericの変更 ========================================= .. post:: Jan 12, 2020 :tags: ada, ada_2022 いくら細部が重要と言っても細部過ぎて既に意味わからない領域ではないかと思います。 abstract引数とclass-wide版のサブプログラム ------------------------------------------ tagged型のプリミティブには対応するclass-wide版のサブプログラムが用意されます。 .. code-block:: ada generic type T (<>) is tagged private; with procedure Foo (Obj : in T); package P1 is end P1; package A is type Something is tagged null record; procedure Some_Proc (Object : in Something) is null; end A; procedure Unrelated_Proc (Object : in A.Something) is null; package New_P1 is new P1 (A.Something, A.Some_Proc); package New_P1_U is new P1 (A.Something, Unrelated_Proc); package New_P1_CW is new P1 (A.Something'Class, A.Some_Proc); ``New_P1_CW`` では ``P1`` の ``Foo`` として渡しているのは暗黙に用意された ``procedure Some_Proc (Object : in Something'Class);`` です。 (またGNATのバグを見つけたような気がします。 規格ではAda 2012以降でこのコードは通るはずです。) さて ``generic`` のサブプログラムの仮引数に ``abstract`` を付けますとプリミティブしか受け付けなくなります。 .. code-block:: ada generic type T (<>) is tagged private; with procedure Foo (Obj : in T) is abstract; package P2 is end P2; package New_P2 is new P2 (A.Something, A.Some_Proc); package New_P2_U is new P2 (A.Something, Unrelated_Proc); -- error package New_P2_CW is new P2 (A.Something'Class, A.Some_Proc); -- error パッケージの外で宣言した ``Unrelated_Proc`` を弾くようになりました。 ついでに最後のclass-wide版も弾かれました。 class-wide版のサブプログラムはプリミティブではないからです。 ところが ``generic`` をもうひとつ挟むことでエラーになったはずのclass-wide版を通すことができます。 .. code-block:: ada generic type NT (<>) is new A.Something with private; package Gr is package New_P2_In_Gr is new P2 (NT, Some_Proc); end Gr; package New_Gr_CW is new Gr (A.Something'Class); 一度 ``A.Something`` (またはそこから派生した)型と限定した ``NT`` を介しています。 ``A.Something`` はプリミティブ ``Some_Proc`` を持っていますので ``NT`` でも ``Some_Proc`` は使えます。 ですので ``New_P2_In_Gr`` は合法です。 基底型を限定した仮引数にclass-wide型を渡すのも合法ですので ``New_Gr_CW`` も合法です。 回避できるのに ``New_P2_CW`` を弾く意味がないということで修正されます。 Ada 202xでは ``abstract`` のついたサブプログラムの仮引数がclass-wide版のサブプログラムを受け付けるようになります。 念の為に書いておきますとclass-wide版のサブプログラムといってもプリミティブに対応するものだけです。 野良で宣言したものは弾かれます。 .. code-block:: ada procedure Unrelated_CW_Proc (Object : in A.Something'Class) is null; package New_P2_CW is new P1 (A.Something'Class, A.Some_Proc); package New_P2_U is new P1 (A.Something'Class, Unrelated_CW_Proc); -- error Pure/Preelaborateとネストされたgeneric -------------------------------------- これまで規格の文面では翻訳単位の ``Pure``/``Preelaborate`` がネストされた ``generic`` にまで影響していなかったらしいです。 .. code-block:: ada package Outer with Pure is generic package Inner is procedure Dummy; end Inner; end Outer; package body Outer is package body Inner is Variable : Integer; procedure Dummy is begin null; end Dummy; end Inner; end Outer; 禁止しておかないと ``Inner`` をインスタンス化することで ``Pure`` な翻訳単位にグローバル変数を作ることができてしまいます。 実際この ``Variable`` はGNATもAdaMagicという古いコンパイラも弾くそうです。 Ada 202xでは規格の文面でも禁止されました。 関連AI ------ - `AI12-0165-1`_ **Operations of class-wide types and formal abstract subprograms** - `AI12-0232-1`_ **Rules for pure generic bodies** .. _`AI12-0165-1`: http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai12s/ai12-0165-1.txt .. _`AI12-0232-1`: http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai12s/ai12-0232-1.txt