如何将多个std :: function合并为一个?

时间:2017-03-14 03:47:19

标签: c++ c++11 stl std-function stdbind

我有多个std::function。它们中的每一个都有不同的输入和输出,一个std::function的输入可能是另一个std::function的输出,这意味着" serial"从一个转换为另一个。

也许我无法清楚地描述它。让代码谈谈

std::function<bool(double)> combine(std::function<int(double)> convert1
                                    , std::function<char(int)> convert2
                                    , std::function<bool(char)> convert3)
{
    return std::bind(convert1, convert2, convert3)//error. A function directly convert [double] to [bool] using convert1, convert2, convert3
}

这是一个非常简单的代码,我已经删除了无意义的代码并显示了我的意思的核心。

因此,您可以看到convert1double转换为intconvert2int转换为char和{{1}从convert3转换为char。现在我需要将它们组合在一起,以便我可以直接将bool转换为double

而且您知道,我真的不想将bool转换为double。它仅用于测试。

实现这一点的一个选择是编写帮助功能:

bool

但它的代码很难看,也许我会以一种常见的方式使用这种转换,这意味着我应该为所有类型的转换编写bool helper(double d , std::function<int(double)> convert1 , std::function<char(int)> convert2 , std::function<bool(char)> convert3) { return convert3(convert2(convert1(d))); } std::function<double(bool)> combine(std::function<int(double)> convert1 , std::function<char(int)> convert2 , std::function<bool(char)> convert3) { return helper; }

那么,有没有直接的方法将这些功能组合在一起?

3 个答案:

答案 0 :(得分:3)

你可以使用lambda表达式来做到这一点。

SELECT s.date, s.rate, MAX(p.percent) AS maxperc, MIN(p.percent) AS minperc
    FROM stock s
    LEFT JOIN promotions p ON s.date = p.date
    WHERE s.date BETWEEN '2017-01-29' AND '2017-01-31'
    GROUP BY s.date,s.rate;

或者您可以直接在代码中使用lambda,并且根本不使用此$array=[]; $i=0; while($row=mysqli_fetch_assoc($result)){ $array[0][$i]["date"]=$row["date"]; $array[0][$i]["rate"]=$row["rate"]; $array[0][$i]["perc"]=$row["minperc"]; $array[1][$i]["date"]=$row["date"]; $array[1][$i]["rate"]=$row["rate"]; $array[1][$i]["perc"]=$row["maxperc"]; ++$i; } 函数,也会更清楚发生了什么。

如果你仍然想要使用组合功能并想要更通用的功能,也许你可以试试这样的东西。 (只是一个简单的例子)

std::function<bool(double)> combine(std::function<int(double)> convert1
                                    , std::function<char(int)> convert2
                                    , std::function<bool(char)> convert3)
{
    return [=](double d){return convert3(convert2(convert1(d)));}
}

答案 1 :(得分:2)

创建简单类型特征以提取最后一个函数的输入类型

template <typename, typename...>
struct lastFnType;

template <typename F0, typename F1, typename ... Fn>
struct lastFnType<F0, F1, Fn...>
 { using type = typename lastFnType<F1, Fn...>::type; };

template <typename T1, typename T2>
struct lastFnType<std::function<T2(T1)>>
 { using type = T1; };

你可以在一个更通用的可变参数模板递归解决方案中转换苹果苹果的解决方案(+1)

template <typename T1, typename T2>
std::function<T1(T2)> combine (std::function<T1(T2)> conv)
 { return conv; }

template <typename T1, typename T2, typename T3, typename ... Fn>
std::function<T1(typename lastFnType<std::function<T2(T3)>, Fn...>::type)>
    combine (std::function<T1(T2)> conv1, std::function<T2(T3)> conv2, 
             Fn ... fn)
 {
   using In = typename lastFnType<std::function<T2(T3)>, Fn...>::type;

   return [=](In const & in){ return conv1(combine(conv2, fn...)(in)); };
 }

但请注意转换器的顺序是反转的(首先使用上次使用的转换器调用;所以combine(convert3, convert2, convert1)

以下是一个完整的例子

#include <functional>

template <typename, typename...>
struct lastFnType;

template <typename F0, typename F1, typename ... Fn>
struct lastFnType<F0, F1, Fn...>
 { using type = typename lastFnType<F1, Fn...>::type; };

template <typename T1, typename T2>
struct lastFnType<std::function<T2(T1)>>
 { using type = T1; };

template <typename T1, typename T2>
std::function<T1(T2)> combine (std::function<T1(T2)> conv)
 { return conv; }

template <typename T1, typename T2, typename T3, typename ... Fn>
std::function<T1(typename lastFnType<std::function<T2(T3)>, Fn...>::type)>
    combine (std::function<T1(T2)> conv1, std::function<T2(T3)> conv2, 
             Fn ... fn)
 {
   using In = typename lastFnType<std::function<T2(T3)>, Fn...>::type;

   return [=](In const & in){ return conv1(combine(conv2, fn...)(in)); };
 }

int fn1 (double d)
 { return d*2.0; }

char fn2 (int i)
 { return i+3; }

bool fn3 (char c)
 { return c == 'a'; }


int main ()
 {
   std::function<int(double)> f1 { fn1 };
   std::function<char(int)> f2 { fn2 };
   std::function<bool(char)> f3 { fn3 };

   auto cmb = combine(f3, f2, f1);

   bool b { cmb(3.2) };
 }

答案 2 :(得分:0)

您可以这样做:

template <typename T, typename F>
decltype(auto) apply(T&& t, F&& f)
{
    return std::forward<F>(f)(std::forward<T>(t));
}

template <typename T, typename F, typename... Fs>
decltype(auto) apply(T&& t, F&& f, Fs&&... fs)
{
    return apply(std::forward<F>(f)(std::forward<T>(t)), std::forward<Fs>(fs)...);
}

用法:

apply(4,
      [](int i) { return i * 10; },
      [](auto i) {return i + 2;},
      [](auto n){ return n / 10.f; })

Demo