У меня есть бесплатные функции foo
, которые перегружены для определенных пользователем типов X
следующим образом (C
является библиотечным типом, вызывающим foo
):
template <typename C>
void foo(C&, const X&) {...}
Я могу определить во время компиляции, существует ли перегрузка для определенного типа 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, "");
}
};
Теперь предположим следующую иерархию классов с перегрузками foo
для Base
и 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; }
Как определить, что при вызове foo(..., Leaf())
будет вызываться перегрузка const Derived&
?
В общем:
Я хочу проверить точный тип foo
, чтобы выяснить, перегружена ли функция для определенного типа X
. существуют; если он не существует, я хочу знать, существуют ли другие перегрузки функций для базовых типов X
, и если да, то какая из них будет вызываться при передаче ему аргумента типа const X&
.
Информация «какой» должна содержать базовый тип, который для приведенного выше примера будет Derived
(а не Base
).