Preamble:
switch(nValue)
{
case X:
...
case Y:
...
default:
ASSERT_FOR_DEFAULT(nValue);
}
ASSERT_FOR_DEFAULT
is a macro, that will display a (custom) assertion dialog, to report hitting "default-case". Yes, this macro is for run-time assertion, not for compile time assertion. But, I just need that, any constant-value (compile-time) cannot be passed to this macro.
Problem:
Following should fail at compilation:
ASSERT_FOR_DEFAULT(5);
Yes, programmer may use it anywhere, not just in default
case of a switch-case
. He may also use any expression which is not used in switch
. But that's not the issue. Just need that only non-constant should be passed to this macro.
There is nothing important written for this macro, just assume it is ASSERT
/assert
.
I have tried with templates (used them other SFINAE/static-asserts!), arrays (like strcpy_s
), own struct having YES
, NO
types and what not. But couldn't find the solution!
I am using VC2008. I am aware of static_assert
, decltype
etc, but cannot use C++0x.
EDIT (Solution):
#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!
}
Thanks to Arne Mertz for this lovely suggestion. I derived the solution from it.
noConstAllowed
is overloaded for all T&
types, and if constant value is passed, the another overload will be called. Both have different return types, and thus checking against the size. Templated version returns a bool
, which satisfies the assert for any variable passed, and fails for any constant, or expression (since return type would be int
).