C++の属性(アトリビュート)とは?主要な標準属性の使い方を徹底解説
属性(アトリビュート)とは
属性(アトリビュート)は、同じコードを異なるコンパイラで動作させても一貫した挙動を実現するための、C++のモダンな仕組みです。属性を使うことでコンパイラに追加情報を与え、条件(制約)の強制、最適化、必要に応じた特定のコード生成を行わせることができます。
属性はコンパイラにとっての一種の「情報マニュアル」のようなものであり、コードのパフォーマンス向上につながる各種の制御を行うために活用されます。属性はC++11で初めて導入され、それ以来C++の重要な要素となっています。さらに、バージョンが上がるごとに改訂が重ねられ、より強力で使いやすいものへと進化し続けています。
C++における属性の定義方法
C++のバージョンによって、属性を定義する構文は異なります。
C++11で属性を作成する構文:
[[attribute-list]]
C++17で属性を作成する構文:
[[using attribute-namespace : attribute-list]]
C++20で属性を作成する構文:
[[contract-attribute-token contract-level-identifier : expression]]
多くの属性は、変数・関数・クラスなどに対して使用できます。それでは、属性とは何か、どのように機能し、どのように定義するのかがわかったところで、C++で利用できるさまざまな標準属性を見ていきましょう。
C++11で導入された属性
noreturn
関数が値を返さないことをコンパイラに伝える属性です。
構文
[[noreturn]]
使用例
[[noreturn]] void f();
この関数はいかなる値も返しません。voidですら返しません。noreturn属性を使うと、無限ループやエラーなどによって処理が呼び出し元に戻らないような状況が発生した場合に、コンパイラが警告を発するようになります。
carries_dependency
release-consumeメモリオーダリングにおける依存関係を定義し、不要なメモリ消費命令を経由しないことで、コンパイラが最適化を行えるようにする属性です。
構文
[[carries_dependency]]
主に関数やパラメータの宣言とともに使用され、依存関係を明示します。
deprecated
コード内の非推奨エンティティを定義する属性です。非推奨エンティティの使用自体は許可されていますが、使用は推奨されません。
構文
[[deprecated]] [[deprecated (reason)]]
reasonには、非推奨化の理由を示す文字列を指定でき、非推奨エンティティの代替手段を提示することもできます。非推奨にできるエンティティは、クラス、構造体、共用体、typedef名、静的メンバー、関数、名前空間、列挙型などです。
fallthrough
switch文で次のcaseへのフォールスルーが意図的なものであることをコンパイラに示す属性です。これにより、コンパイラはフォールスルーに対する警告を発しなくなります。
構文
[[fallthrough]]
fallthroughは、次のcaseが定義されているswitch文でのみ使用できます。
nodiscard
戻り値を持つ関数の戻り値が破棄された場合(voidへキャストせずに捨てられた場合)に、コンパイラへ警告を発させる属性です。
構文
[[nodiscard]] [[nodiscard (reason)]](C++20で追加)
reasonは、戻り値を破棄すべきでない理由を示す文字列であり、C++20から利用可能になりました。
maybe_unused
未使用のエンティティが存在する場合に表示される警告を抑制するよう、コンパイラに指示する属性です。
構文
[[maybe_unused]]
maybe_unusedを宣言できるエンティティは、クラス、構造体、共用体、typedef名、静的メンバー、関数、変数、列挙型などです。
likely、unlikely
分岐の実行パスが、現在の実行パスよりも起こりやすいか、起こりにくいかをコンパイラに伝える属性です。
構文
[[likely]] [[unlikely]]
これらは一般に、ラベルや文など、プログラムの実行フローを変える要素に対して適用されます。
no_unique_address
特定のアドレスを持つ必要のないデータメンバーを定義する属性です。一般に、非静的データメンバーの個別のメモリ割り当てが必須でない場合に使用されます。
構文
[[no_unique_address]]
通常の変数とno_unique_address指定の変数の間でメモリ位置を割り当てる必要がある場合、コンパイラは前者を優先します。
optimize_for_synchronized
指定された関数の定義が、synchronizedステートメントからの呼び出しに向けて最適化されるべきであることを定義する属性です。
構文
[[optimize_for_synchronized]]
optimize_for_synchronizedとして定義された関数は、synchronizedブロックの直列化を回避します。
expects
関数が実行されるために、引数が満たすべき必須条件を指定する属性です。
構文
[[expects : condition]]
conditionには、関数が実行されるために満たされるべき条件を定義します。
属性を使う理由 ― 属性が解決する課題とは?
以上が、C++11からC++20までに定義されている属性です。ここからは、なぜプログラミングにおいて属性が使われるのか、つまり属性がどのような課題を解決するのかを見ていきましょう。
コードに制約を追加する − 多くの場合、属性はコードに意味を与え、より妥当性の高いコードにするとともに、余計な手間を削減します。
コンパイラに追加の最適化情報を提供する − fallthrough、likely、maybe_unusedなどの属性は、コンパイラが特定の最適化を行うための情報を提供します。
警告やエラーの回避 − プログラマの意図したロジックが、C++の厳格なルールと衝突することがあります。こうした場面で属性が役立ち、発生するはずの警告を回避・抑制できます。
-
C#の属性(Attribute)とは?基本構文と主な定義済み属性をわかりやすく解説
C#における属性(Attribute)とは、クラス、メソッド、構造体、列挙型、アセンブリなど、プログラムを構成するさまざまな要素の動作に関する情報を、実行時(ランタイム)に伝えるための宣言型のタグです。 属性を使うことで、コード自体には手を加えずに、追加のメタデータを要素へ付与することができます。 属性の基本構文 属性は以下のような形式で記述します。 [attribute(positional_parameters, name_parameter = value, ...)] Element この構文のポイントは次のとおりです。 属性名とその値は角括弧 [ ] の中に記述します。 属性は、適
-
C#のObsolete属性とは?使い方と警告・エラーの出力方法を解説
C#のObsolete属性とは メソッドにObsolete属性(廃止属性)を付けると、そのコードがコンパイルされる際に、コンパイラが警告またはエラーメッセージを出力します。 クラスに新しいメソッドを追加した後でも、旧メソッドを残しておきたいケースがあります。このような場合、旧メソッドをObsolete属性でマークし、「旧メソッドの代わりに新メソッドを使用してください」というメッセージを表示させることができます。これにより、旧メソッドの利用者に対して非推奨であることを明確に伝えられます。 Obsolete属性の使用例 以下は、Obsolete属性を使用したサンプルコードです。 using Sy