将双变量std :: function转换为单变量std :: function

时间:2015-06-18 02:50:15

标签: c++ c++11 lambda

我有一个函数,它获取两个值x和y,并返回结果:

std::function< double( double, double ) > mult = 
  []( double x, double y){ return x*y; };

现在我想得到一个常量y的单变量函数。我编写了以下代码,但它不起作用。

std::function<
  std::function< double(double) > (
    std::function< double(double, double) >,
    double
  )
> funcYgivenX =
  [](std::function< double(double, double) > func2d, double inX) {
    return [&func2d, &inX]( double inY ) {
      return func2d(inX, inY);
    };
  };

我在这里做错了什么?什么是最好(最有效)的方法呢?

3 个答案:

答案 0 :(得分:9)

在C ++ 11中std::bind基本上已经过时,引入了lambdas。 这是使用lambda绑定的一个例子。

int add(int a, int b) {return a + b;}

int main() {
  auto add2 = [](int a){ return add(a,2); };

  std::cout << add2(3) << std::endl; // prints 5
}

关于lambdas优先于std::bind的参考,可以阅读Scott Meyers撰写的 Effective Modern C ++ ,第32项。在C ++ 11中,它无法移动捕获使用lambda,此行为只能使用std::bind进行模拟。通过在C ++ 14中引入lambdas的init捕获,即使是那个角落的情况也可以用lambdas很好地解决。

答案 1 :(得分:4)

不不不。 这就是std::bind的存在!

#include <iostream>
#include <functional>
#include <typeinfo>

int add(int a, int b) {return a + b;}

int main() {

    //I believe this here is just a special type of bound function.
    auto add2 = std::bind(add, std::placeholders::_1, 2);

    //Yup.
    std::cout << typeid(add2).name() << std::endl;
    //Here's the type of the first function.
    std::cout << typeid(add).name() << std::endl;
    //The new function.
    std::cout << add2(1) <<  std::endl;

    return 0;   
}

http://coliru.stacked-crooked.com/a/56c0459617ba61d5

你要做的就是提供函数,然后提供你想要作为std::bind的辅助参数提供给新函数的参数,并用`std :: placeholders :: _ X替换任何“空格” ,其中X是第n个参数号,从第一个参数的1开始。

你甚至可以实现闭包!

http://coliru.stacked-crooked.com/a/0b43fe3d1651fe36

#include <iostream>
#include <functional>
#include <typeinfo>
#include <vector>

int add(int a, int b) {return a + b;}

int main() {

    std::vector<std::function<int(int)>> funcs;

    for (int i = 0; i < 5; ++i) {
        auto f = std::bind(add, std::placeholders::_1, i+1);
        funcs.push_back(f);
    }


    int i = 0;
    for (int k = 0; k > -10; k = k - 2) {
        std::cout << funcs[i](k) << std::endl;
        ++i;
    }

    return 0;   
}

如果你愿意,你也可以使用lambdas;他们往往也更清洁,你可以避免讨厌的std::bind

类型

http://coliru.stacked-crooked.com/a/9df068bc41beb8ea

#include <iostream>
#include <functional>
#include <typeinfo>
#include <vector>

int add(int a, int b) {return a + b;}

int main() {

    std::vector<std::function<int(int)>> funcs;

    for (int i = 0; i < 5; ++i) {
        auto f = [i](int j) {return(i + j);};
        funcs.push_back(f);
    }


    int i = 0;
    for (int k = 0; k > -10; k = k - 2) {
        std::cout << funcs[i](k) << std::endl;
        ++i;
    }

    return 0;   
}

答案 2 :(得分:1)

使用时

x

您正在通过引用捕获变量return [&func2d, &inX]( double inY ){ return func2d(inX, inY); }; func2d,当函数inX返回时,变量成为悬空引用。

将功能更改为按值捕获。

funcYgivenX

使用时

std::function< std::function< double(double) >(std::function< double(double, double) >, double) > funcYgivenX
  = [](std::function< double(double, double) > func2d, double inX)
  {
    return [func2d, inX]( double inY ){ return func2d(inX, inY); };
  };

您正在按值捕获变量return [func2d, inX]( double inY ){ return func2d(inX, inY); }; func2d,即使在函数inX返回后仍然有效。

这就是第二个版本在第一个版本导致未定义行为时的原因。

请参阅以下工作代码:http://ideone.com/X1CRGC