我有一个函数,它获取两个值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);
};
};
我在这里做错了什么?什么是最好(最有效)的方法呢?
答案 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。