前文:
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)であるため。