I have the following tag dispatching code (see LiveWorkSpace)
#include <iostream>
// traits types
struct A {}; struct B {}; struct C {};
// helpers
void fun_impl(bool, A) { std::cout << "A\n"; }
void fun_impl(bool, B) { std::cout << "B\n"; }
// would like to eliminate this
void fun_impl(bool b, C)
{
if(b)
fun_impl(b, A());
else
fun_impl(b, B());
}
template<typename T>
void fun(bool b, T t)
{
// T = A, B, or C
fun_impl(b, t);
}
int main()
{
fun(true, A()); // "A"
fun(false, A()); // "A"
fun(true, B()); // "B"
fun(false, B()); // "B"
fun(true, C()); // "A"
fun(false, C()); // "B"
}
However, this tag disptatching is closely tied to the function fun
and I need to maintain 3 helper functions to implement this tag dispatching for every function that uses this.
Argument deduction fail: I have tried to abstract the fun_impl
into a template parameter of a mixed_dispatch
function object, but if I then pass fun_impl
as an argument, it cannot be deduced which of the 2 overloads should be required.
template<typename T>
struct mixed_dispatch
{
template<typename Fun>
void operator()(Fun f, bool b)
{
return f(b, T());
}
};
template<>
struct mixed_dispatch<C>
{
template<typename Fun>
void operator()(Fun f, bool b)
{
if (b)
return f(b, A());
else
return f(b, B());
}
};
template<typename T>
void fun(bool b, T)
{
// T = A, B, or C
mixed_dispatch<T>()(fun_impl, b); // ERROR: Fun cannot be deduced
}
Question: is there any other way to decouple the tag dispatching from the function being called?
I'm open to any suggestions using C++11 variadic templates / Boost.Fusion or other wizardry that simplifies my current code (I now have to maintain 3 instead of 2 helper functions for every function that uses this specific dispatch, and with more complicated dispatching the number of helper functions grows even faster).