Consider the following code, where the functor derivedinherits from two base classes base1and base2, each of which provides different overloads:
#include <iostream>
#include <functional>
#include <type_traits>
struct base1 {
void operator()(int) const {
std::cout << "void base1::operator()(int) const\n";
}
void operator()(double) const {
std::cout << "void base1::operator()(double) const\n";
}
template <class Arg, class... Args>
void operator()(const Arg&, Args&&...) const {
std::cout << "void base1::operator()(const Arg&, Args&&...) const\n";
}
};
struct base2 {
void operator()(int) {
std::cout << "void base2::operator()(int)\n";
}
void operator()(double) {
std::cout << "void base2::operator()(double)\n";
}
};
struct derived: base1, base2 {
using base1::operator();
using base2::operator();
void operator()(char) {
std::cout << "void derived::operator()(char)\n";
}
};
template <class F, class... Args>
void call(F&& f, Args&&... args) {
std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
}
int main(int argc, char* argv[]) {
const derived d1;
derived d2;
derived d3;
call(d1, 1);
call(d2, 1);
call(d1, 1, 2);
call(d2, 1, 2);
call(d3, 'a');
return 0;
}
Resulting result:
void base1::operator()(int) const
void base2::operator()(int)
void base1::operator()(const Arg&, Args&&...) const
void base1::operator()(const Arg&, Args&&...) const
void derived::operator()(char)
which illustrates that, depending on the arguments, the selected overload may come from base1, base2or derived.
My question is : could one do the same at compile time by creating a type character that would determine which class provided the selected overload?
This will take the form:
template <
class Base1, // Possibly cv-ref qualified base1
class Base2, // Possibly cv-ref qualified base2
class Derived, // Possibly cv-ref qualified derived
class... Args // Possibly cv-ref qualified args
>
struct overload_origin {
using base1 = std::decay_t<Base1>;
using base2 = std::decay_t<Base2>;
using derived = std::decay_t<Derived>;
using type =
call overload_origin::type base1, base2, base1, base1, derived .
?