属性指定子シーケンス (C++11以降)
型、オブジェクト、コードなどに対して実装定義の属性を導入します。
目次 |
[編集] 構文
[[ attribute-list ]] |
(C++11以降) | ||||||||
[[ using attribute-namespace : attribute-list ]] |
(C++17以降) | ||||||||
ここで、attribute-list は、0個以上の属性をコンマで区切ったシーケンスです(省略記号...で終わる場合があり、これはパック展開を示します)。
| identifier | (1) | ||||||||
attribute-namespace :: identifier |
(2) | ||||||||
identifier ( argument-list(optional) ) |
(3) | ||||||||
attribute-namespace :: identifier ( argument-list(optional) ) |
(4) | ||||||||
ここで、attribute-namespace は identifier であり、argument-list は、括弧、角括弧、波括弧が釣り合っているトークンのシーケンスです (balanced-token-seq)。
|
属性リストの冒頭に `using namespace:` が現れる場合、その属性リスト内の他の属性は名前空間を指定できません。using で指定された名前空間がそれらすべてに適用されます。 [[using CC: opt(1), debug]] // same as [[CC::opt(1), CC::debug]] [[using CC: CC::opt(1)]] // error: cannot combine using and scoped attribute |
(C++17以降) |
[編集] 説明
属性は、GNUやIBMの言語拡張 __attribute__((...))、Microsoftの拡張 __declspec() など、実装定義の言語拡張に対して統一された標準構文を提供します。
属性はC++プログラムのほとんどどこでも使用でき、型、変数、関数、名前、コードブロック、翻訳単位全体など、ほとんどすべてに適用できますが、それぞれの特定の属性は、実装によって許可されている場所でのみ有効です。例えば、[[expect_true]]はifでのみ使用でき、クラス宣言では使用できない属性かもしれません。[[omp::parallel()]]はコードブロックやforループに適用できる属性かもしれませんが、型intには適用できません(これら2つの属性は架空の例であり、標準属性や一部の非標準属性については以下を参照してください)。
宣言では、属性は宣言全体の前に現れることも、宣言されるエンティティの名前の直後に現れることもでき、その場合は結合されます。他のほとんどの状況では、属性は直前のエンティティに適用されます。
alignas指定子は属性指定子シーケンスの一部ですが、構文が異なります。[[...]]属性が現れる場所で現れることができ、それらと混在することができます(ただし、alignasが許可されている場所で使用される場合)。
2つの連続した左角括弧トークン ([[) は、属性指定子を導入する場合、または属性引数の内部でのみ現れることができます。
void f() { int y[3]; y[[] { return 0; }()] = 1; // error int i [[cats::meow([[]])]]; // OK }
以下にリストされている標準属性の他に、実装は実装定義の動作を持つ任意の非標準属性をサポートする場合があります。実装に未知のすべての属性は、エラーを引き起こすことなく無視されます。(C++17以降)
|
attribute-namespace を持たない属性、および名前が |
(C++20以降) |
[編集] 標準属性
以下の属性はC++標準によって定義されています。
標準属性は構文的に無視できません。構文エラーを含まず、正しいターゲットに適用されなければならず、引数内のエンティティはODR-useされなければなりません。
標準属性は意味的にも無視できません。特定の標準属性のすべてのインスタンスが削除された場合の動作は、属性が存在する元のプログラムの適合する動作であったはずです。
[[noreturn]](C++11) |
関数が戻らないことを示します (属性指定子) |
| (C++11)(C++26で削除) |
リリース-コンシュームstd::memory_orderにおける依存関係チェーンが関数内外に伝播することを示します (属性指定子) |
[[deprecated]][[deprecated("reason")]](C++14)(C++14) |
この属性で宣言された名前またはエンティティの使用は許可されるが、何らかの理由で推奨されないことを示します (属性指定子) |
[[fallthrough]](C++17) |
前のケースラベルからのフォールスルーが意図的なものであり、フォールスルーについて警告するコンパイラによって診断されるべきではないことを示します (属性指定子) |
[[maybe_unused]](C++17) |
もしあれば、未使用のエンティティに関するコンパイラの警告を抑制します (属性指定子) |
| 戻り値が破棄された場合にコンパイラが警告を発するように促します (属性指定子) | |
| コンパイラが、文を通る実行パスが他の実行パスよりも可能性が高い、または低い場合に最適化すべきであることを示します (属性指定子) | |
| (C++20) |
非静的データメンバが、そのクラスの他のすべての非静的データメンバと異なるアドレスを持つ必要がないことを示します (属性指定子) |
[[assume(expression)]](C++23) |
特定の時点でexpressionが常にtrueに評価されることを指定します (属性指定子) |
[[indeterminate]](C++26) |
初期化されていない場合、オブジェクトが不定値を持つことを指定します (属性指定子) |
| (TM TS) |
関数定義が同期ステートメントからの呼び出し用に最適化されるべきであることを示します (属性指定子) |
[編集] 注意
特定のプラットフォーム上での各属性の存在は、__has_cpp_attributeプリプロセッサマクロで確認できます。
| 機能テストマクロ | 値 | 規格 | 機能 |
|---|---|---|---|
__cpp_attributes |
200809L |
(C++11) | 属性 |
__cpp_namespace_attributes |
201411L |
(C++17) | 名前空間の属性 |
[編集] 例
[[gnu::always_inline]] [[gnu::hot]] [[gnu::const]] [[nodiscard]] inline int f(); // declare f with four attributes [[gnu::always_inline, gnu::const, gnu::hot, nodiscard]] int f(); // same as above, but uses a single attr specifier that contains four attributes // C++17: [[using gnu : const, always_inline, hot]] [[nodiscard]] int f[[gnu::always_inline]](); // an attribute may appear in multiple specifiers int f() { return 0; } int main() {}
[編集] 欠陥レポート
以下の動作変更を伴う欠陥報告が、以前に公開されたC++標準に遡って適用されました。
| DR | 適用対象 | 公開された動作 | 正しい動作 |
|---|---|---|---|
| CWG 2079 | C++11 | [[ は属性引数の中に現れることができませんでした |
許可 |
| CWG 2538 | C++11 | 標準属性が構文的に無視できるかどうかが不明確でした | 禁止された |
| CWG 2695 | C++11 | 標準属性が意味的に無視できるかどうかが不明確でした | 禁止された |
| P2156R1 | C++11 | すべての標準属性は、attribute-list に最大1回しか現れないことが要求されていました | 要求されない |
[編集] 関連項目
__has_cpp_attribute - 属性の存在をチェックします | |
| C言語ドキュメント:属性指定子シーケンス
|
[編集] 外部リンク
| 1. | GCCの属性。これらの属性は[[gnu::...]]として使用できます。SOを参照。 |
| 2. | Clangの属性. |
| 3. | MSVCの属性. |