双折表达式替换分支语句

问题描述 投票:0回答:1

我正在尝试找出如何使用折叠表达式(或其他元编程技术)来摆脱下面代码片段中的“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 不是一个选择。

c++ variadic-templates template-meta-programming fold
1个回答
0
投票

沿着这些思路(未测试):

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;
};
© www.soinside.com 2019 - 2024. All rights reserved.