属性
AttributeSpecifier: Attribute : Attribute DeclarationBlock Attribute: AlignAttribute AtAttribute DeprecatedAttribute FunctionAttributeKwd LinkageAttribute Pragma VisibilityAttribute abstract auto const final __gshared extern immutable inout override ref return scope shared static synchronized FunctionAttributeKwd: nothrow pure AtAttribute: @ disable @ nogc @ live Property @ safe @ system @ trusted UserDefinedAttribute Property: @ property DeclarationBlock: DeclDef { DeclDefsopt }
属性は、1つまたは複数の宣言を修正する方法である。 一般的な形式は以下の通りである。
attribute declaration; // 宣言に影響する attribute: // 現在のスコープが終了するまで、すべての宣言に影響する // 現在のスコープ declaration; declaration; ... attribute { // ブロック内のすべての宣言に影響する declaration; declaration; ... }
リンク属性
LinkageAttribute: extern ( LinkageType ) extern ( C ++ , ) extern ( C ++ , QualifiedIdentifier ) extern ( C ++ , NamespaceList ) extern ( C ++ , class ) extern ( C ++ , struct ) LinkageType: C C ++ D Windows System Objective - C NamespaceList: ConditionalExpression ConditionalExpression, ConditionalExpression, NamespaceList
Dは、C関数とオペレーティングシステムのAPI関数を簡単に呼び出す方法を提供する。 両者との互換性は不可欠である。 LinkageTypeは大文字と小文字が区別され、 実装によって拡張可能である(キーワードではない)。C とD は必須であり、他のものは 実装に意味があるものである。C++ はC++との限定的な互換性を提供する。 詳細は「C++とのインターフェイス」の ドキュメントを参照のこと。 Objective-C Objective-Cとの互換性を提供しており、 詳細は「Objective-Cとのインターフェイス」のドキュメントを参照のこと。System はWindowsプラットフォームではWindows と同じであり、 他のプラットフォームではC と同じである。
Implementation Note: Win32プラットフォームの場合は、Windows が存在する必要がある。
C関数の呼び出し規約は、 以下によって指定される。
extern (C): int foo(); // foo()をCで呼び出す。extern(C) は、struct やclass を含むすべての宣言に対して提供できることに 注意すること。ただし、C 側には対応する一致するものがない。その場合、 属性は無視される。この動作は、ネストされた 関数やネストされた変数にも適用される。ただし、static メンバ メソッドおよびstatic ネストされた関数では、extern(C) を追加すると 呼び出し規約は変更されるが、マングリングは変更されない。
D 規約は以下の通り:
extern (D):
Windows APIの規約は:
extern (Windows): void *VirtualAlloc( void *lpAddress, uint dwSize, uint flAllocationType, uint flProtect );
Windowsの規約は、Win32プラットフォーム上でのみC規約と異なり、 ここで stdcall規約と同等となる。
extern キーワードが単独で ストレージクラスとして使用されていることに注意。
C++ ネームスペース
リンク形式extern (C++, QualifiedIdentifier) は、C++ ネームスペースに存在する C++ 宣言を作成する。QualifiedIdentifier は ネームスペースを指定する。
extern (C++, N) { void foo(); }
C++宣言を参照している。
namespace N { void foo(); }
修飾語句を付けても付けなくても参照できる。
foo(); N.foo();
名前空間は、囲むスコープにインポートされる新しい名前付きスコープを作成する。
extern (C++, N) { void foo(); void bar(); } extern (C++, M) { void foo(); } void main() { bar(); // OK //foo(); // エラー - N.foo()またはM.foo() ? M.foo(); // OK }
QualifiedIdentifier内の複数のドット付き識別子は、ネストされた名前空間を作成する。
extern (C++, N.M) { extern (C++) { extern (C++, R) { void foo(); } } } N.M.R.foo();
C++宣言を参照している。
namespace N { namespace M { namespace R { void foo(); } } }
align 属性
AlignAttribute: align align ( AssignExpression )
配置を指定する:
- 変数
- 構造体フィールド
- 共用体フィールド
- クラスフィールド
- 構造体、共用体、クラス型
align それ自体では デフォルトに設定され、これは、対応するCコンパイラのデフォルトのメンバー整列と一致する。
struct S { align: byte a; // オフセット0に配置 int b; // オフセット4に配置 long c; // オフセット8に配置 } static assert(S.alignof == 8); static assert(S.c.offsetof == 8); static assert(S.sizeof == 16);
AssignExpressionは、 デフォルト以外のアラインメントが使用される場合の、コンパニオンCコンパイラの動作に一致するアラインメントを指定する。 これは、2のべき乗でなければならない。
値が1の場合は、整列は行われず、 フィールドはまとめてパックされる。
struct S { align (1): byte a; // オフセット0に配置 int b; // オフセット1に配置 long c; // オフセット5に配置 } static assert(S.alignof == 1); static assert(S.c.offsetof == 5); static assert(S.sizeof == 13);
集約の自然なアラインメントは、そのフィールドの最大のアラインメントである。 アラインメントをアグリゲートの外部で設定することで、これを上書きすることができる。
align (2) struct S { align (1): byte a; // オフセット0に配置 int b; // オフセット1に配置 long c; // オフセット5に配置 } static assert(S.alignof == 2); static assert(S.c.offsetof == 5); static assert(S.sizeof == 14);
フィールドのアラインメントを設定すると、フィールドのサイズに関係なく、2のべき乗にアラインメントが設定される。
struct S { byte a; // オフセット0に配置 align (4) byte b; // オフセット4に配置 align (16) short c; // オフセット16に配置 } static assert(S.alignof == 16); static assert(S.c.offsetof == 16); static assert(S.sizeof == 32);
AlignAttributeは、 関数スコープまたは匿名でない構造体、共用体、クラスに入るときにデフォルトにリセットされ、 そのスコープを抜けると元に戻る。 これは基底クラスから継承されない。
参照:構造体レイアウト。
GC 互換性
NewExpressionを使用して割り当てられた参照またはポインタをsize_t の倍数ではない境界で整列しない こと。 ガベージコレクタは、 GCによって割り当てられたオブジェクトへのポインタおよび参照がsize_tバイト境界にあると想定している。
struct S { align(1): byte b; int* p; } static assert(S.p.offsetof == 1); @safe void main() { S s; s.p = new int; // エラー: @safeコードでミスアラインドポインタを変更できない }
deprecated 属性
DeprecatedAttribute: deprecated deprecated ( AssignExpression )
ライブラリ内の機能を廃止する必要がある場合でも、 後方互換性を維持するためにそれを保持しておく必要がある場合がよくある。そのような 宣言はdeprecated としてマークすることができ、
deprecated { void oldFoo(); } oldFoo(); // 非推奨: 関数test.oldFooは非推奨である
オプションとして、文字列リテラルまたはマニフェスト定数を使用して 、非推奨メッセージに追加情報を提供することができる。
deprecated("Don't use bar") void oldBar(); oldBar(); // 非推奨: 関数test.oldBarは非推奨 - barを使わないでほしい
CTFE対応関数を呼び出したり、マニフェスト定数を使用することも可能である。
import std.format; enum message = format("%s and all its members are obsolete", Foobar.stringof); deprecated(message) class Foobar {} deprecated(format("%s is also obsolete", "This class")) class BarFoo {} void main() { auto fb = new Foobar(); // 非推奨: class test.Foobarは非推奨 - Foobar // およびそのすべてのメンバは廃止された auto bf = new BarFoo(); // 非推奨: class test.BarFooは非推奨 - この // クラスも廃止されている }
Implementation Note: コンパイラには、 を無視するか、警告を発するか、コンパイル時にエラーとするかを指定するスイッチがあるはずだ。 deprecated
可視性属性
VisibilityAttribute: export package package ( QualifiedIdentifier ) private protected public
可視性は、private 、package 、protected 、public 、またはexport のいずれかの属性である。 DIP22より前の文書では、これらの属性は保護属性と呼ばれることがある。
可視性はシンボル名の検索に関与する。
export 属性
export シンボルが実行可能ファイル、共有ライブラリ、または DLL の外部からアクセスできることを意味する。 シンボルは、実行可能ファイル、共有ライブラリ、または DLL で定義された場所からエクスポートされ、別の実行可能ファイル、共有ライブラリ、または DLL でインポートされる。
をexport シンボルの定義に適用された場合は、それをエクスポートする。 が シンボルの宣言に適用された場合は、それをインポートする。 が適用されない限り、変数は定義である。export extern
export int x = 3; // 定義、`x`のエクスポート export int y; // 定義、`y`のエクスポート export extern int z; // 宣言、`z`のインポート export __gshared h = 3; // 定義、`h`のエクスポート export __gshared i; // 定義、`i`のエクスポート export extern __gshared int j; // 宣言、`j`のインポート
本体のある関数は定義であり、本体のないものは宣言である。
export void f() { } // 定義, `f`のエクスポート export void g(); // 宣言, `g`のインポート
Windows用語では、dllexportはDLLからシンボルをエクスポートすることを意味し、dllimportは DLLまたは実行可能ファイルがDLLからシンボルをインポートすることを意味する。
package 属性
package private を拡張し、パッケージのメンバーが 同じパッケージ内の他のモジュール内のコードからアクセスできるようにする。 識別子が指定されていない場合、これは最も内側のパッケージのみに適用される。 または、モジュールがパッケージ内にネストされていない場合は、 をデフォルトとする。 private
package ドット区切りの識別子リスト形式のオプションパラメータを指定できる。 これは修飾パッケージ名として解決される。パッケージはモジュールの 親パッケージ、またはその祖先パッケージのいずれかでなければならない。このパラメータが指定されている場合、シンボルは 指定されたパッケージとそのすべての子孫で表示される。
private 属性
private の可視性を持つシンボルは、 同じモジュール内からのみアクセスできる。 プライベートメンバ関数は暗黙的に final オーバーライドすることはできません。
protected 属性
protected クラス(およびテンプレート化された関数)内部でのみ適用され、 同じモジュールのメンバー、または派生クラスによってのみシンボルを参照できることを意味する。 派生クラスのメンバー関数を通じてプロテクトされたインスタンスメンバーにアクセスする場合、 そのメンバーは 暗黙的に 'this' と同じ型にキャストできるオブジェクトインスタンスに対してのみアクセスできる。 モジュールメンバーは無効である。 protected
public 属性
public 実行可能ファイル内のコードはすべてメンバーを参照できることを意味する。 これはデフォルトの可視性属性である。
変更可能属性
const 属性
const 型修飾子は、 宣言されたシンボルの型をT からconst(T) に変更する。ここで、T は、const が指定されていない場合に導入されたシンボルに対して指定(または推論)された型である。
const int foo = 7; static assert(is(typeof(foo) == const(int))); const double bar = foo + 6; static assert(is(typeof(bar) == const(double)));
class C { const void foo(); const { void bar(); } void baz() const; } pragma(msg, typeof(C.foo)); // const void() pragma(msg, typeof(C.bar)); // const void() pragma(msg, typeof(C.baz)); // const void() static assert(is(typeof(C.foo) == typeof(C.bar)) && is(typeof(C.bar) == typeof(C.baz)));
参照:修飾された型の返却方法。
immutable 属性
immutable 属性は、T からimmutable(T) に型を変更する。 これは、const と同じ方法である。参照:
inout 属性
inout 属性は、T からinout(T) に型を変更する。 これは、const と同じ方法である。
共有ストレージの属性
shared 属性
参照 shared。
__gshared 属性
デフォルトでは、不変ではないグローバル宣言はスレッドローカルストレージに格納される。 グローバル変数が__gshared属性でマークされている場合、その値はすべてのスレッドで共有される。
int foo; // 各スレッドはfooの排他的コピーを持つ。 __gshared int bar; // barはすべてのスレッドで共有される。
__gshared メンバ変数やローカル変数にも適用できる。 これらの場合、 は と同等であるが、 ただし、変数はスレッドローカルではなく、すべてのスレッドで共有される。__gshared static
class Foo { __gshared int bar; } int foo() { __gshared int bar = 0; return bar++; // スレッドセーフではない。 }
警告: xml-ph-0000@deepl.internalは、属性とは異なり、 shared属性とは異なり、__gshared は データ競合やその他のマルチスレッドの同期に関する問題に対する 保護機能を提供しない。__gshared とマークされた変数へのアクセスが正しく同期されるようにすることは、プログラマーの責任である。
__gshared @safe コードでは許可されていない。
synchronized 属性
「同期クラス」を参照。
@disable 属性
属性でマークされた宣言への参照は、 コンパイル時にエラーを引き起こす。これは、特定の 操作やオーバーロードをコンパイル時に明示的に許可しないようにするために使用できる。@disable 属性が指定された宣言を参照すると、 コンパイル時にエラーが発生する。これは、 実行時にエラーが発生するのを待つのではなく、コンパイル時に特定の操作やオーバーロードを明示的に禁止する ために使用できる。
@disable void foo() { }
xml-ph-0000@deepl.internal
void main() { foo(); /* error, foo is disabled */ }
@disable this(); 構造体内ではデフォルトのコンストラクションが禁止される。
構造体のコピーコンストラクタを無効にすると、 その構造体はコピーできなくなる。
、 xml-ph-0000@deepl.internal、xml-ph-0001@deepl.internal 属性@safe、@trusted 、@system 属性
関数安全を参照。
システム変数
@system とマークされた変数は、@safe コードからアクセスできない。
@system int* p; struct S { @system int i; } void main() @safe { int x = *p; // error with `-preview=systemVariables`, deprecation otherwise S s; s.i = 0; // ditto }
関数属性
@nogc 属性
No-GC関数を参照。
@property 属性
プロパティ関数」を参照。
nothrow 属性
Nothrow関数を参照。
pure 属性
純粋関数を参照。
ref 属性
ref ストレージクラスを参照。
return 属性
static 属性
static 属性は、型、関数、データに適用される。static は、他の宣言に適用される場合は無視される。
集約型内部では、static 宣言はオブジェクトの特定のインスタンスには適用されず、 オブジェクトの型に適用される。 つまり、this 参照は存在しないということである。
class Foo { static int x; static int bar() { return x; } int foobar() { return 7; } } Foo.x = 6; // インスタンスは必要ない assert(Foo.bar() == 6); //Foo.foobar(); // エラー、Fooのインスタンスがない。 Foo f = new Foo; assert(f.bar() == 6); assert(f.foobar() == 7);
静的メソッドは決して仮想ではない。
静的データはオブジェクトごとに1つではなく、スレッドごとに1つのインスタンスを持つ。
静的ネスト関数 または型は、 親スコープ内の変数にアクセスできない。
関数内部では、静的ローカル変数は関数が返された後も保持される。
Staticは、C言語における「ファイルローカル」という追加の意味を持たない。 その機能を実現するには、D言語の属性を使用する。 private Dの属性を使用して、それを実現する。 例えば:
module foo; int x = 3; // xはグローバルである。 private int y = 4; // yはモジュールfooのローカル変数であるxml-ph-0000@deepl.internalxml-ph-0000@deepl.internal
auto 属性
auto 属性は、他の属性がなく 型推論が必要な場合に
auto i = 6.8; // iをdoubleとして宣言する
関数では、auto 属性は戻り値の型推論を意味する。 "auto関数"を参照。
scope 属性
scope 属性は、変数のポインタ値が、その変数が宣言されたスコープから外に出ないことを意味する。
変数の型に間接参照が含まれない場合、scope 属性は無視される。
グローバル変数に適用された場合、scope も無視される。なぜなら、ポインタがエスケープできるスコープはグローバルスコープより大きいものはないからだ。
scope int* x; // スコープは無視され、グローバル変数となる void main() { // scope static int* x; // スコープとstaticの両方にはできない scope float y; // スコープは無視され、遠まわしな表現をしない scope int[2] z; // スコープは無視され、静的配列は値型である scope int[] w; // スコープ動的配列 }
間接参照を持つ型のローカル変数に適用した場合、 その変数の値は、より長い寿命を持つ変数に割り当てられない可能性がある。
- スコープ文の外にある変数(その変数が宣言されているスコープ文の外にある変数
- scope 変数より前に宣言された変数。ローカル変数は宣言された順序と逆の順序で破棄されるため、
- __gshared 、または 変数static
また、より長い寿命を持つ変数に暗黙的に代入する他の操作も許可されない。
- 関数からscope 変数を返す
- 関数を呼び出すことで、scope 変数を非スコープパラメータに割り当てる
- scope 変数を配列リテラルに入れる
scope 属性は変数宣言の一部であり、型ではない。また、これは間接参照の第一レベルにのみ適用される。 例えば、変数をスコープポインタの動的配列として宣言することはできない。なぜなら、scope は配列自体の.ptrのみに適用され、その要素には適用されないからだ。scope は、以下のようにさまざまな型に影響する。
Type of local variable | What scope applies to |
---|---|
すべての基本データ型 | なし |
ポインタ T* | ポインタ値 |
動的配列 T[] | .ptr を要素に |
静的配列 T[n] | 各要素T |
連想配列 K[V] | ポインタを処理系定義の構造体へ |
struct またはunion | 各メンバ変数への |
function ポインタ | ポインタ値 |
デリゲート | .funcptr と.ptr (クロージャコンテキスト)の両方のポインタ値を |
class またはinterface | クラス参照 |
列挙型 | 基本型 |
struct S { string str; // 注釈: string = immutable(char)[] string* strPtr; } string escape(scope S s, scope S* sPtr, scope string[2] sarray, scope string[] darray) { return s.str; // 無効、スコープは構造体メンバに適用される return *s.strPtr; // 有効、scope構造体メンバーは再参照される return sPtr.str; // 有効、構造体ポインタは再参照される return *sPtr.strPtr; // 有効、2つのポインタが参照解除される return sarray[0]; // 無効、スコープは静的配列要素に適用される return sarray[1]; // 無効、同上 return darray[0]; // 有効、スコープは要素ではなく配列ポインタに適用される }
スコープ値
scope 変数の値、またはスタック割り当てメモリを指す生成された値を「scope 値」と呼ぶ。 このような値は、スタティック配列をスライスするか、 または スタックに割り当てられた(または割り当てられる可能性がある)変数へのポインタを作成することで生成される。
- 関数パラメータ
- ローカル変数
- 暗黙的なthis パラメータを通じてアクセスされる"構造体"のメンバー
- Ref関数の戻り値
Typesafe 可変長引数関数からの可変長引数もスコープ値である。 引数はスタック上に渡されるためである。
ローカル変数にscope の値が代入される場合、その変数に明示的な型が指定されていてauto キーワードを使用していない場合でも、scope と推論される。
@safe: ref int[2] identity(return ref int[2] x) {return x;} int* escape(int[2] y, scope int* z) { int x; auto xPtr = &x; // `scope int*`と推論される int[] yArr = identity(y)[]; // `scope int[]`と推論される int* zCopy = z; // `scope int*`と推論される return zCopy; // エラー } void variadic(int[] a...) { int[] x = a; // `scope int[]`と推論される } void main() { variadic(1, 2, 3); }
struct S { int x; // このメソッドは、スタックに確保されたSのインスタンスに対して呼び出すことができる void f() { int* p = &x; // `scope int* p`と推論される int* q = &this.x; // 等価 } }
スコープパラメータは、スコープローカル変数と同じように扱われるが、 関数に関数属性推論がある場合は、それらを返すことが許可される。 その場合、それらはリターンスコープパラメータとして推論される。
scope クラスインスタンス
クラスインスタンスを直接割り当てるために使用される場合、scope 変数はRAII (リソース取得は初期化である)プロトコルを意味する。 これは、オブジェクトの参照がスコープ外に出たときに、オブジェクトのデストラクタが自動的に呼び出されることを意味する。 デストラクタは、 例外がスローされてスコープから抜けた場合でも呼び出されるため、scopeは
クラスがnew で構築され、scope のローカル変数に割り当てられる場合、 スタック上に割り当てられ、@nogc のコンテキストで許可される可能性がある。
scope クラスの変数が同時にスコープから外れるものが複数ある場合、 そのデストラクタは、 変数が構築された順序と逆の順序で呼び出される。
クラス型のscope 変数への代入は、 初期化以外では許可されていない。なぜなら、そうすると変数の適切な破棄が複雑になるからだ。
import core.stdc.stdio : puts; class C { ~this() @nogc { puts(__FUNCTION__); } } void main() @nogc { { scope c0 = new C(); // スタックに割り当てられる scope c1 = new C(); //c1 = c0; // エラー: スコープ変数を結合し直すことができない // ここでは`c1`と`c0`のデストラクタが順に呼び出される } puts("bye"); }
OOP 属性
abstract 属性
抽象クラスは派生クラスによってオーバーライドされなければならない。 抽象メンバ関数を宣言すると、クラスが抽象クラスとなる。
final 属性
- クラスは、 finalサブクラス化を 禁止することができます。
- クラス・メソッドを宣言して、 final 派生クラスがそれをオーバーライドできないように宣言できる。
- インターフェースはfinal メソッドを定義できる。
override 属性
仮想関数」を参照。
属性@mustuse 属性
@mustuse 属性は、Dランタイムモジュールで定義されたコンパイラ認識の ユーザー定義属性である。 core.attribute。
式は、以下のいずれかが真である場合にのみ破棄されるとみなされる。以下のいずれかが真である場合、式は破棄されるとみなされる。
以下のすべてが真である場合、式を破棄することはコンパイル時のエラーである。
- 代入式、インクリメント式、またはデクリメント式ではない 。
- その型は、struct またはunion 型であり、宣言に@mustuse の注釈が付いている。
「代入式」とは、 単純代入式または 代入 演算子式を意味する。
「インクリメント式」とは、演算子が++であるUnaryExpressionまたはPostfixExpressionを意味する。
「減算式」とは、演算子が--であるUnaryExpressionまたは PostfixExpressionを意味する。
@mustuse を関数宣言に結び付けること、またはstruct またはunion 宣言以外の集約宣言に結び付けることは、コンパイル時のエラーとなる。 この規則の目的は、将来的な拡張の可能性を考慮して、そのような用法を確保することである。
ユーザー定義属性
UserDefinedAttribute: @ ( TemplateArgumentList ) @ TemplateSingleArgument @ Identifier ( NamedArgumentListopt ) @ TemplateInstance @ TemplateInstance ( NamedArgumentListopt )
ユーザー定義属性(UDA)は、宣言に付加できるコンパイル時の注釈である。 これらの属性は、コンパイル時に問い合わせ、抽出、操作することができる。 これには実行時コンポーネントは存在しない。
ユーザー定義属性は、以下を使用して定義される。- コンパイル時の式
- 名前付きマニフェスト定数
- 型名
- コンパイル時の引数リストを使用してインスタンス化する型
@(3) int a; // 値の引数 @("string", 7) int b; // 複数の値 // コンパイル時定数を使用する enum val = 3; @val int a2; // `a`と同じ属性を持つ enum Foo; @Foo int c; // 型名の属性 struct Bar { int x; } @Bar() int d; // 型インスタンス @Bar(3) int e; // イニシャライザを使った型インスタンス
e Bar の場合、この属性は、 静的に初期化される 引数を使用する
宣言のスコープに複数のUDAが存在する場合、それらは連結される。
@(1) { @(2) int a; // UDA (1, 2)を持つ @("string") int b; // UDA (1, "string")を持つ }
関数パラメータはUDAを持つことができる。
xml-ph-0000@deepl.internalvoid f(@(3) int p);
__traits(getAttributes)
UDAは、 を使用して コンパイル時のシーケンスに抽出できる。UDAは、__traits を使用してコンパイル時のシーケンスに抽出できる。
@('c') string s; pragma(msg, __traits(getAttributes, s)); // tuple('c')を表示する。
シンボルにユーザー定義の属性がない場合は、空のシーケンスが返される。 結果は、コンパイル時のシーケンスと同様に使用できる。つまり、インデックス付けや テンプレートパラメータとして渡すことができるなどである。
enum e = 7; @("hello") struct SSS { } @(3) { @(4) @e @SSS int foo; } alias TP = __traits(getAttributes, foo); pragma(msg, TP); // tuple(3, 4, 7, (SSS))を表示する pragma(msg, TP[2]); // 7を表示する
シーケンス内の任意の型を使用して、さまざまなものを宣言できる。
TP[3] a; // aはSSSとして宣言される
型名の属性は変数の属性とは異なる。
pragma(msg, __traits(getAttributes, a)); // tuple()を表示する pragma(msg, __traits(getAttributes, typeof(a))); // タプル("hello")を表示する
使用法
もちろん、UDAの真価は、特定の値を持つユーザー定義型を作成できることにある。 基本型の属性値を持つだけではスケールしない。 xml-ph-0000@deepl.internal
属性が値であるか型であるかはユーザー次第であり、後から 追加された属性が以前の属性を上書きするかどうかは、ユーザーが属性をどのように解釈するかによって決まる 。
テンプレート
UDAがテンプレート宣言に添付されている場合、そのUDAは自動的に そのテンプレートのインスタンスのすべての直接メンバに添付される。それらのメンバのいずれかが テンプレートである場合、このルールは再帰的に適用される。
@("foo") template Outer(T) { struct S { int x; } int y; void fun() {} @("bar") template Inner(U) { int z; } } pragma(msg, __traits(getAttributes, Outer!int.S)); // tuple("foo")を表示する pragma(msg, __traits(getAttributes, Outer!int.S.x)); // tuple()を表示する pragma(msg, __traits(getAttributes, Outer!int.y)); // tuple("foo")を表示する pragma(msg, __traits(getAttributes, Outer!int.fun)); // tuple("foo")を表示する pragma(msg, __traits(getAttributes, Outer!int.Inner)); // tuple("foo", "bar")を表示する pragma(msg, __traits(getAttributes, Outer!int.Inner!int.z)); // tuple("foo", "bar")を表示する
UDAはテンプレートパラメータに添付できない。
DEEPL APIにより翻訳、ところどころ修正。
このページの最新版(英語)
このページの原文(英語)
翻訳時のdmdのバージョン: 2.109.1
ドキュメントのdmdのバージョン: 2.109.1
翻訳日付 :
HTML生成日時:
編集者: dokutoku