应用一组N个函数中的第一个有效函数 [英] Apply the first valid function of a set of N functions

查看:77
本文介绍了应用一组N个函数中的第一个有效函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

上一个答案显示了如何基于调用的有效性来应用功能:此处.但是,它适用于两个功能.我想知道是否可以使用C ++ 14中的智能模板编程技巧将这一概念推广到N函数.

This previous answer shows how to apply function based on the validity of a call: here. However, it applies to two functions. I was wondering if the concept could be generalized to N functions using smart template programming tricks, in C++14.

问题如下:

template <std::size_t N, class... X>
/* [Return type] */ apply_on_validity(X&&... x)
{
    // Tricks here
}

// The function would be equivalent to a hypothetical
// template <std::size_t N, class... F, class... Args>
// [Return type] apply_on_validity(F&&... f, Args&&... args)
// where N = sizeof...(F) is the number of functions

在执行方面:

apply_on_validity<3>(f1, f2, f3, a, b, c, d, e);

会:

  • 如果表达式有效,则调用f1(a, b, c, d, e),否则
  • 如果表达式有效,则调用f2(a, b, c, d, e),否则
  • 如果表达式有效,则调用f3(a, b, c, d, e),否则
  • 什么都不做
  • call f1(a, b, c, d, e) if the expression is valid, otherwise
  • call f2(a, b, c, d, e) if the expression is valid, otherwise
  • call f3(a, b, c, d, e) if the expression is valid, otherwise
  • do nothing

在所有情况下,它都会返回已执行函数的结果.

And in all cases, it would return the result of the function that was executed.

在调用方,模板参数3表示已指定的功能数.

On the calling side, the template parameter 3 indicates the number of functions that have been specified.

它在C ++ 14中可行吗?如果可以,怎么办?

Is it doable in C++14, and if so, how?

推荐答案

这里是踢球的另一个有趣之处,它滥用了超载分辨率.我们将把每个函数转换成带有rank参数的另一个函数,将所有函数组合在一起,然后调用它们.选择会从过载集合中自然消失.

Here's another fun one for kicks, abusing overload resolution. We're going to transform each function into another function that takes a rank argument, combine all of our functions together, and then just invoke them. The selection will just fall out naturally from the overload set.

我们的排名只是这种类型的阶梯:

Our ranker is just this ladder of types:

template <int I> struct rank : rank<I-1> { };
template <> struct rank<0> { };

我们需要一个功能转换器:

We need a function transformer:

template <class T, class F>
auto prepend_arg(F&& f) {
    return [f=std::forward<F>(f)](T, auto&&... args)
        -> decltype(std::forward<F>(f)(std::forward<decltype(args)>(args)...))
    {
        return std::forward<F>(f)(std::forward<decltype(args)>(args)...);
    };
}

然后:

template <std::size_t N, std::size_t... Is, std::size_t... Js,
    class... X>
decltype(auto) apply_impl(std::index_sequence<Is...>,
                          std::index_sequence<Js...>,
                          X&&... x)
{
    auto all = std::forward_as_tuple(std::forward<X>(x)...);

    return overload(
        // all of our function cases
        prepend_arg<rank<N-Is>>(std::get<Is>(all))...,
        // base case: do nothing
        [](rank<0>, auto&&...) {}
    )(rank<N>{}, std::get<N+Js>(all)...);
//               ^^^^^^^^^^^^^^^^^^^^^^^^
//               pass in all the arguments    
}

template <std::size_t N, class... X>
decltype(auto) apply_on_validity(X&&... x) {
    return apply_impl<N>(
        std::make_index_sequence<N>{},
        std::make_index_sequence<sizeof...(X)-N>{},
        std::forward<X>(x)...);
}

我将overload()留作练习.

这篇关于应用一组N个函数中的第一个有效函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆