I am trying to figure out how to use fold expressions ( or other metaprogramming techniques) to get rid off "if else" branches in the code snippet below.
template<typename ... Ts>
struct VisitorAny
{
template<typename Callable>
auto apply_visitor(Callable&& callable, const std::any& data1, const std::any& data2)
{
using first_type = std::tuple_element_t<0, std::tuple<Ts...>>;
using R = decltype(std::declval<Callable>()(std::declval<first_type>(), std::declval<first_type>()));
//std::cout << "Return type is " << typeid(R).name() << std::endl;
R ret{};
if (data1.type() == typeid(int) && data2.type() == typeid(int))
{
ret = std::forward<Callable>(callable)(std::any_cast<int>(data1), std::any_cast<int>(data2));
}
else if (data1.type() == typeid(float) && data2.type() == typeid(int))
{
ret = std::forward<Callable>(callable)(std::any_cast<float>(data1), std::any_cast<int>(data2));
}
else if (data1.type() == typeid(int) && data2.type() == typeid(float))
{
ret = std::forward<Callable>(callable)(std::any_cast<int>(data1), std::any_cast<float>(data2));
}
else if (data1.type() == typeid(float) && data2.type() == typeid(float))
{
ret = std::forward<Callable>(callable)(std::any_cast<float>(data1), std::any_cast<float>(data2));
}
//(((data1.type() == typeid(Ts)) ? ((), false) : true) && ...);
return ret;
}
};
In the case of a callable which accepts just one instance of std::any, it is straightforward
template<typename Tany, typename Tr, typename Callable>
void visit(const Tany& any_inp, Tr& ret, Callable&& callable)
{
ret = std::forward<Callable>(callable)(any_inp);
};
template<typename Callable>
auto apply_visitor(Callable&& callable, const std::any& data)
{
using first_type = std::tuple_element_t<0, std::tuple<Ts...>>;
using R = decltype(std::declval<Callable>()(std::declval<first_type>()));
//std::cout << "Return type is " << typeid(R).name() << std::endl;
R ret{};
(((data.type() == typeid(Ts)) ? ((visit(std::any_cast<Ts>(data), ret, callable)), false) : true) && ...);
return ret;
};
I wonder how a similar technique can be used for a callable that accepts two instances of std::any. Using std::visit and std::variant is not an option.
Something along these lines (not tested):