static_assert(...) 'C++0x'
が問題を優雅に解決する例を教えてください。static_assertは何を行いますか?それは何のために使用しますか?
私は実行時に慣れていますassert(...)
。いつ普通のassert(...)
よりもstatic_assert(...)
を好むべきですか?
また、boost
には、BOOST_STATIC_ASSERT
と呼ばれるものがあります。これはstatic_assert(...)
と同じですか?
static_assert(...) 'C++0x'
が問題を優雅に解決する例を教えてください。static_assertは何を行いますか?それは何のために使用しますか?
私は実行時に慣れていますassert(...)
。いつ普通のassert(...)
よりもstatic_assert(...)
を好むべきですか?
また、boost
には、BOOST_STATIC_ASSERT
と呼ばれるものがあります。これはstatic_assert(...)
と同じですか?
... SomeLibrary::Version
はむしろ#define
D(1がC++ライブラリに期待するもの)であることよりも、静的定数として宣言されると仮定すると
#include "SomeLibrary.h"
static_assert(SomeLibrary::Version > 2,
"Old versions of SomeLibrary are missing the foo functionality. Cannot proceed!");
class UsingSomeLibrary {
// ...
};
。
実際SomeLibrary
し、コードをコンパイルすることでコントラストは、すべてをリンクし、あなたがSomeLibrary
の互換性のないバージョンをコンパイルする30分を費やしたことを見つけるためにのみその後、を実行可能ファイルを実行します。
@Arak、あなたのコメントに反応して:はい、あなたが持つことができますstatic_assert
それを見てから、どこ、ただ座っ:
class Foo
{
public:
static const int bar = 3;
};
static_assert(Foo::bar > 4, "Foo::bar is too small :(");
int main()
{
return Foo::bar;
}
$ g++ --std=c++0x a.cpp a.cpp:7: error: static assertion failed: "Foo::bar is too small :("
static_assert
を1つ使用すると、構造(ネットワークやファイルなどの外部世界とのインターフェイス)が期待どおりのサイズになるようにすることができます。これは、誰かがその結果を実現することなく構造からメンバーを追加または変更する場合を捉えます。 static_assert
はそれを受け取り、ユーザーに警告します。私の頭の上オフ
私はコンパイラの動作についての私の仮定を確保するためにそれを使用します、ヘッダー、libs、そして自分のコードさえ正しいです。例えばここでは、構造体が予想されたサイズに正しくパックされていることを確認します。クラスのラップで
struct LogicalBlockAddress
{
#pragma pack(push, 1)
Uint32 logicalBlockNumber;
Uint16 partitionReferenceNumber;
#pragma pack(pop)
};
BOOST_STATIC_ASSERT(sizeof(LogicalBlockAddress) == 6);
stdio.h
さんfseek()
、私はenum Origin
で、いくつかのショートカットを取り、それらのショートカットがstatic_assert
assert
を超えるときは、選ぶべきstdio.h
uint64_t BasicFile::seek(int64_t offset, enum Origin origin)
{
BOOST_STATIC_ASSERT(SEEK_SET == Origin::SET);
によって定義された定数に合わせていることを確認しています動作はコンパイル時に定義され、実行時では定義されていません。これがではなく、である例では、パラメーターと戻りコードの検査が含まれます。
BOOST_STATIC_ASSERT
は、条件が満たされない場合に不正なコードを生成するプレC++ 0xマクロです。その意図は同じですが、static_assert
が標準化されており、より良いコンパイラ診断を提供する可能性があります。
スタティックアサートは、コンパイル時にアサーションを行うために使用されます。静的アサーションが失敗すると、プログラムは単純にコンパイルされません。これは、正確に32ビットのunsigned int
オブジェクトに非常に依存するコードによっていくつかの機能を実装する場合など、さまざまな状況で便利です。このような静的なアサーションを置くことができます
static_assert(sizeof(unsigned int) * CHAR_BIT == 32);
別のプラットフォームでは、異なるサイズのunsigned int
タイプではコンパイルが失敗するため、開発者はコードの問題の部分に注意を向け、コードを再実装または再検査するようにアドバイスします。
別たとえば、あなたがvoid *
関数へのポインタ(ハックが、時には便利です)など、いくつかの整数値を渡すこともできますし、あなたは積分値がポインタ
int i;
static_assert(sizeof(void *) >= sizeof i);
foo((void *) i);
あなたはchar
タイプが負の値で
static_assert(CHAR_MIN < 0);
またはその整数分周を締結している資産にしたいかもしれませんが、ゼロ
に向けて丸めstatic_assert(-5/2 == -2);
など。
多くの場合、静的アサーションの代わりにランタイムアサーションを使用できますが、実行時アサーションは実行時にのみ、また制御がアサーションを通過するときにのみ機能します。このため、ランタイムアサートが失敗すると、長期間にわたって検出されずに休止状態になる可能性があります。
もちろん、静的アサーションの式はコンパイル時定数でなければなりません。ランタイム値にすることはできません。実行時の値には他の選択肢はありませんが、通常のassert
を使用します。
BOOST_STATIC_ASSERT
は、static_assert
機能のクロスプラットフォームラッパーです。
現在、クラスに「概念」を適用するためにstatic_assertを使用しています。
例:上記のいずれかの条件が満たされていない場合
template <typename T, typename U>
struct Type
{
BOOST_STATIC_ASSERT(boost::is_base_of<T, Interface>::value);
BOOST_STATIC_ASSERT(std::numeric_limits<U>::is_integer);
/* ... more code ... */
};
これは、コンパイル時にエラーが発生します。
C++ 11がリリースされた(そしてしばらく外出した)ので、static_assertはすべてのメジャーコンパイラのより新しいバージョンでサポートされるべきです。 C++ 14(テンプレートの制約が含まれていることを期待しています)を待つことができない人にとって、これはstatic_assertの非常に便利なアプリケーションです。 – Collin
これは元の質問に直接答えるものではありませんが、C++ 11より前にこれらのコンパイル時間チェックを実施する方法について興味深い研究をしています。
第2章(第2.1節)アンドレイAlexanderscuによってModern C++ Designのこの
template<int> struct CompileTimeError;
template<> struct CompileTimeError<true> {};
#define STATIC_CHECK(expr, msg) \
{ CompileTimeError<((expr) != 0)> ERROR_##msg; (void)ERROR_##msg; }
マクロSTATIC_CHECK比較このようなコンパイル時のアサーションの思想()とstatic_assert()
STATIC_CHECK(0, COMPILATION_FAILED);
static_assert(0, "compilation failed");
Inを実装しますコンセプトの欠如static_assert
は、テンプレートなどの簡単で読みやすいコンパイル時の型チェックに使用できます。
template <class T>
void MyFunc(T value)
{
static_assert(std::is_base_of<MyBase, T>::value,
"T must be derived from MyBase");
// ...
}
さらに詳しいオプションについては、BOOST_MPL_ASSERT、BOOST_MPL_ASSERT_NOT、BOOST_MPL_ASSERT_MSG、BOOST_MPL_ASSERT_RELATION [http://www.boost.org/doc/libs/1_40_0/libs/mpl/doc/refmanual/asserts.html]を参照してください。 _MSGは、使い方を見つけたら特に便利です。 – KitsuneYMG