GOAL:
I would like to achieve type-safe dynamic polymorphism (i.e. run-time dispatch of a function call) on unrelated types
Some time has passed, C++14 is being finalized, and compilers are adding support for new features, like generic lambdas.
Generic lambdas, together with the machinery shown below, allow achieving the desired (dynamic) polymorphism with unrelated classes:
#include
template
class delegating_visitor : public boost::static_visitor
{
public:
delegating_visitor(F&& f) : _f(std::forward(f)) { }
template
R operator () (T x) { return _f(x); }
private:
F _f;
};
template
auto make_visitor(F&& f)
{
using visitor_type = delegating_visitor>;
return visitor_type(std::forward(f));
}
template
auto vcall(V&& vt, F&& f)
{
auto v = make_visitor(std::forward(f));
return vt.apply_visitor(v);
}
#define call_on_variant(val, fxn_expr) \
vcall(val, [] (auto x) { return x-> fxn_expr; });
Let's put this into practice. Supposing to have the following two unrelated classes:
#include
#include
struct A
{
int foo(int i, double d, std::string s) const
{
std::cout << "A::foo(" << i << ", " << d << ", " << s << ")";
return 1;
}
};
struct B
{
int foo(int i, double d, std::string s) const
{
std::cout << "B::foo(" << i << ", " << d << ", " << s << ")";
return 2;
}
};
It is possible to invoke foo()
polymorphically this way:
int main()
{
A a;
B b;
boost::variant v = &a;
auto res1 = call_on_variant(v, foo(42, 3.14, "Hello"));
std::cout << std::endl<< res1 << std::endl;
v = &b;
auto res2 = call_on_variant(v, foo(1337, 6.28, "World"));
std::cout << std::endl<< res2 << std::endl;
}
And the output is, as expected:
A::foo(42, 3.14, Hello)
1
B::foo(1337, 6.28, World)
2
The program has been tested on VC12 with November 2013's CTP. Unfortunately, I do not know of any online compiler that supports generic lambdas, so I cannot post a live example.