It is impossible to use TAG_A
and TAG_B
in a case
of a switch
, except by using preprocessor tricks like stringifying the macro replacement itself in a macro and then parsing the value form the resulting string, which will however make the construct dependent on the exact form of the TAG_X
macros and I feel is not really worth it when you don't have a strict requirement to obtain compile-time constant values representing the pointers.
The results of the expressions produced by the TAG_A
and TAG_B
replacement can not be used in a case
operand because the operand must be a constant expression, but casting an integer to a pointer as done with (A*)
and (B*)
disqualifies an expression from being a constant expression.
So, you will need to use if
/else if
instead:
unsigned int get_tag_address(unsigned int i)
{
if(i == reinterpret_cast<unsigned int>(TAG_A)) {
return 1;
} else if(i == reinterpret_cast<unsigned int>(TAG_B)) {
return 2;
} else {
return 3;
}
}
Also, consider using std::uintptr_t
instead of unsigned int
for i
and in the reinterpret_cast
s, since it is not guaranteed that unsigned int
is large enough to hold the pointer values. However, compilation of the reinterpret_cast
should fail if unsigned int
is in fact too small. (It is possible that std::uintptr_t
in <cstdint>
does not exist, in which case you are either using pre-C++11 or, if not that, it would be a hint that the architecture does not allow for representing pointers as integer values. It is not guaranteed that this is possible, but you would need to be working some pretty exotic architecture for it to not be possible.)
And if you can, simply pass, store and compare pointers (maybe as void*
) instead of integer values representing the pointers. That is safer for multiple reasons and always guaranteed to work.