Static assertは、条件が満たされない場合にコンパイル時にエラーを生成するコンパイラのメカニズムです。この機能はC++11以降に導入され、テンプレートプログラミングを容易にし、コードの品質を向上させるために使用されます。
問題の歴史。
static_assertが登場する前は、プログラマーは配列の負のサイズを持つ構造体(たとえば、char arr[condition?1:-1];のようなもの)を使っていました。これは読みやすさが欠け、エラーの診断が困難でした。そのため、意味のあるメッセージを持つコンパイル時のエラーを明示的に宣言する必要が生じました。
問題。
テンプレートプログラミングでは、適切でない型またはパラメータを持つオブジェクトの生成を禁止するなど、早期診断が必要な場合がよくあります。静的なチェックがないと、そのようなエラーは最終コードのコンパイル段階(時には突然起こる悪い説明のないエラー)でのみ発生します。
解決法。
static_assertというキーワードは、ブール式とメッセージの文字列を受け取ります。式が偽であれば、コンパイルはエラーとなり、メッセージが出力されます。
コードの例:
static_assert(sizeof(int) >= 4, "int must be at least 4 bytes"); template<typename T> void foo(const T& obj) { static_assert(std::is_copy_constructible<T>::value, "T must be copy-constructible"); }
主な特徴:
第二引数なしでstatic_assertを使用できますか?
はい、C++17以降、第二引数は任意です:
static_assert(sizeof(double) == 8); // メッセージはデフォルトになります
条件がテンプレートパラメータに依存する場合でも、static_assertは実行されますか?テンプレートがインスタンス化されない場合はどうでしょうか?
いいえ、static_assertはインスタンス化のポイントに達したときだけ発生します。これにより、使用されているテンプレートのみのチェックが可能になります。
ランタイムの式をstatic_assertの中で使用できますか?
いいえ、式はコンパイル時に評価可能である必要があります(constexpr)。式がconstexprでない場合はコンパイルエラーです。
コードで、ランタイムでのみ計算される式を持つstatic_assertを使用したため(たとえば、入力の読み取りによるファイルサイズ)、システム全体で理解できないコンパイルエラーが発生しました。
利点:
欠点:
テンプレートMatrixがPlain Old Data(POD)型のみで構築できることを保証する必要があります。
template<typename T> class Matrix { static_assert(std::is_pod<T>::value, "Matrix can be instantiated only for POD types"); // ... };
利点:
欠点: