我正在尝试找出如何使用折叠表达式(或其他元编程技术)来摆脱下面代码片段中的“if else”分支。
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;
}
};
对于只接受一个 std::any 实例的可调用函数,这很简单
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;
};
我想知道如何将类似的技术用于接受两个 std::any 实例的可调用对象。 使用 std::visit 和 std::variant 不是一个选择。
沿着这些思路(未测试):
template<typename Data1, typename Tr, typename Callable>
void visit(const Data1& data1, const std::any& data2, Tr& ret, Callable&& callable)
{
((data2.type() == typeid(Ts) ?
((ret = std::forward(callable)(data1, std::any_cast<Ts>(data2))), false)
: true) && ...);
};
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::cout << "Return type is " << typeid(R).name() << std::endl;
R ret{};
(((data1.type() == typeid(Ts)) ?
((visit(std::any_cast<Ts>(data1), data2, ret, std::forward(callable))), false)
: true) && ...);
return ret;
};