For C++, template function can be much more powerful than macro.
template <typename T>
std::string tostring(const T& t);
The drawback of template argument is that it cannot distinguish between typedef aliases:
typedef LONG HRESULT;
For C, I think there is nothing you can do, without changing your structs. If you have control over the struct definitions, here are two tricks:
Add a field to the beginning of the struct, and set the field to a value that uniquely identifies the type of the structure, which can be used by the tostring
function to choose the appropriate printing code.
typedef struct abcde
{
int unique_struct_type_id; // assign this to a number that represents "abcde"
};
A similar method is to pass in a function pointer for printing the struct.
struct abcde
{
void (*print_fn) (abcde* p); // assign this to the printing function for "abcde"
}
#define PRINT_STRUCT(s) s->print_fn(s)