I have free functions foo
which are overloaded for user defined types X
as follows (C
being a library type calling foo
):
template <typename C>
void foo(C&, const X&) {...}
I am able to determine at compile-time whether there exists an overload for a specific type X
:
template <typename... Args>
auto foo_exists(int) -> decltype(std::bind<void(*)(Args...)>(&foo, std::declval<Args>()...), std::true_type());
template <typename... Args>
auto foo_exists(char) -> std::false_type;
struct Caller
{
template <typename T>
void call(const T& x)
{
static_assert(decltype(foo_exists<decltype(*this), const T&>(0))::value, "");
}
};
Now assume the following class hierarchy with foo
overloads for Base
and Derived
:
struct Base{};
struct Derived : Base {};
struct Leaf : Derived{};
template <typename C>
void foo(C&, const Base&) { std::cout << "Base" << std::endl; }
template <typename C>
void foo(C&, const Derived&) { std::cout << "Derived" << std::endl; }
How can I determine that when invoking foo(..., Leaf())
, the const Derived&
overload will be called?
Generically speaking:
I want to test for the exact type of foo
in order to find out whether a function overload for a specific type X
. exists; if it does not exist, I want to know if other function overloads for a base types of X
exist and if yes, which one would be called when passing an argument of type const X&
to it.
The "which" information should contain the base type, which for the above example would be Derived
(and not Base
).