前文:
switch(nValue)
{
case X:
...
case Y:
...
default:
ASSERT_FOR_DEFAULT(nValue);
}
ASSERT_FOR_DEFAULT
「デフォルトの場合」のヒットを報告するための(カスタム)アサーションダイアログを表示するマクロです。はい、このマクロは実行時アサーション用であり、コンパイル時アサーション用ではありません。ただし、必要なのは、定数値(コンパイル時)をこのマクロに渡すことはできないということです。
問題:
以下はコンパイル時に失敗するはずです:
ASSERT_FOR_DEFAULT(5);
はい、プログラマーは、のdefault
場合だけでなく、どこでも使用できますswitch-case
。彼は、で使用されていない任意の式を使用することもできますswitch
。しかし、それは問題ではありません。非定数のみをこのマクロに渡す必要があります。
このマクロについて書かれた重要なことは何もありません。ただASSERT
/であると仮定してassert
ください。
テンプレート(他のSFINAE / static-assertsを使用しました!)、配列(などstrcpy_s
)、独自の構造体YES
、NO
タイプなどを試してみました。しかし、解決策を見つけることができませんでした!
私はVC2008を使用しています。static_assert
、などは知ってdecltype
いますが、C++0xは使えません。
編集(解決策):
#define STATIC_ASSERT(expr) {int array[!!(expr)]; expr;}
template <class T>
bool noConstAllowed(T&);
int noConstAllowed(...);
#define ASSERT_FOR_DEFAULT_VALUE(val) \
{ \
STATIC_ASSERT(sizeof(noConstAllowed(val))==sizeof(bool)); \
}
int main()
{
int test=10;
ASSERT_FOR_DEFAULT_VALUE(test);
ASSERT_FOR_DEFAULT_VALUE(2);
ASSERT_FOR_DEFAULT_VALUE(test+2); //FAILS, but okay for me!
}
この素敵な提案をしてくれたArneMertzに感謝します。私はそれから解決策を導き出しました。
noConstAllowed
はすべてのT&
タイプでオーバーロードされ、定数値が渡されると、別のオーバーロードが呼び出されます。どちらもリターンタイプが異なるため、サイズをチェックします。テンプレート化されたバージョンは、bool
渡された変数のアサートを満たし、定数または式では失敗するを返します(戻り型はint
)であるため。