A coworker recently showed me some code that he found online. It appears to allow compile time determination of whether a type has an "is a" relationship with another type. I think this is totally awesome, but I have to admit that I'm clueless as to how this actually works. Can anyone explain this to me?
template<typename BaseT, typename DerivedT>
inline bool isRelated(const DerivedT&)
{
DerivedT derived();
char test(const BaseT&); // sizeof(test()) == sizeof(char)
char (&test(...))[2]; // sizeof(test()) == sizeof(char[2])
struct conversion
{
enum { exists = (sizeof(test(derived())) == sizeof(char)) };
};
return conversion::exists;
}
Once this function is defined, you can use it like this:
#include <iostream>
class base {};
class derived : public base {};
class unrelated {};
int main()
{
base b;
derived d;
unrelated u;
if( isRelated<base>( b ) )
std::cout << "b is related to base" << std::endl;
if( isRelated<base>( d ) )
std::cout << "d is related to base" << std::endl;
if( !isRelated<base>( u ) )
std::cout << "u is not related to base" << std::endl;
}
It declares two overloaded functions named test
, one taking a Base
and one taking anything (...)
, and returning different types.
It then calls the function with a Derived
and checks the size of its return type to see which overload is called. (It actually calls the function with the return value of a function that returns Derived
, to avoid using memory)
Because enum
s are compile-time constants, all of this is done within the type system at compile-time. Since the functions don't end up getting called at runtime, it doesn't matter that they have no bodies.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With