How can I write a macro that does different things based on the type of its arguments?
I have a macro that needs to handle an argument that can have one of two types.
#include <typeinfo>
enum class Coolness { kUndefined, kUncool, kCool };
enum class Tallness { kUndefined, kShort, kTall };
void MakePerson (Coolness coolness, Tallness tallness) {}
// Provide a way to make a person by only providing Coolness or Tallness.
#define MAKE_PERSON(x) \
({ \
if (typeid(x) == typeid(Coolness)) { \
MakePerson(((x)), Tallness::kUndefined); \
} else { \
MakePerson(Coolness::kUndefined, (x)); \
} \
})
int main()
{
MAKE_PERSON(Coolness::kUncool);
MAKE_PERSON(Tallness::kTall);
}
(We could use default arguments here, but in the real code we effectively must use a macro.)
The compiler throws an error on both calls in main:
main.cpp: In function ‘int main()’:
main.cpp:23:43: error: cannot convert ‘Coolness’ to ‘Tallness’ for argument ‘2’ to ‘void MakePerson(Coolness, Tallness)’
MakePerson(Coolness::kUndefined, (x)); \
^
main.cpp:29:3: note: in expansion of macro ‘MAKE_PERSON’
MAKE_PERSON(Coolness::kUncool);
^~~~~~~~~~~
main.cpp:21:45: error: cannot convert ‘Tallness’ to ‘Coolness’ for argument ‘1’ to ‘void MakePerson(Coolness, Tallness)’
MakePerson(((x)), Tallness::kUndefined); \
^
main.cpp:30:3: note: in expansion of macro ‘MAKE_PERSON’
MAKE_PERSON(Tallness::kTall);
^~~~~~~~~~~
(done on https://www.onlinegdb.com/online_c++_compiler)
We can't use __builtin_types_compatible_p
as in this question because our compiler doesn't have that.
How can I write a macro that does different things based on the type of its arguments?