Raf*_*ini 4 c++ lambda higher-order-functions c++11
我有一个程序,我必须在对每个组件进行一些计算后在屏幕上打印许多STL向量.所以我试着创建一个这样的函数:
template <typename a>
void printWith(vector<a> foo, a func(a)){
for_each(foo.begin(), foo.end(), [func](a x){cout << func(x) << " "; });
}
Run Code Online (Sandbox Code Playgroud)
然后像这样使用它:
int main(){
vector<int> foo(4,0);
printWith(foo, [](int x) {return x + 1;});
return 0;
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,我有一个关于我在printWith调用中放入的lambda表达式类型的编译错误:
g++ -std=gnu++0x -Wall -c vectest.cpp -o vectest.o
vectest.cpp: In function ‘int main()’:
vectest.cpp:16:41: error: no matching function for call to ‘printWith(std::vector<int>&, main()::<lambda(int)>)’
vectest.cpp:10:6: note: candidate is: void printWith()
make: *** [vectest.o] Error 1
Run Code Online (Sandbox Code Playgroud)
当然,如果我这样做:
int sumOne(int x) {return x+1;}
Run Code Online (Sandbox Code Playgroud)
然后printWith(foo, sumOne);按预期工作.我认为lambda表达式的类型将是具有推断返回类型的函数的类型.我也认为我可以在任何可以适合普通功能的地方使用lambda.我该如何工作?
以下适用于我:
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
template <typename a, typename F>
void printWith(vector<a> foo, F f){
for_each(foo.begin(), foo.end(), [&](a x){cout << f(x) << " "; });
}
int main(){
vector<int> foo = {1,2,3,4,5};
printWith(foo, [](int x) {return x + 1;});
std::cout << '\n';
return 0;
}
Run Code Online (Sandbox Code Playgroud)
测试:
$ g++-4.5 -std=gnu++0x -Wall test.cpp
$ ./a.out
2 3 4 5 6
Run Code Online (Sandbox Code Playgroud)
或者,您可以利用没有lambda-capture的闭包类型可以隐式转换为函数指针的事实.这更接近原始代码,并且还减少了函数模板的实例化数量(在原始解决方案中,每次使用具有不同函数对象类型的函数模板时,您都会获得新的实例化;请注意,它不会在这种特殊情况下printWith很重要,因为函数非常短并且很可能总是内联的):
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
template <typename a, typename b>
void printWith(const vector<a>& foo, b f(a)){
for_each(foo.begin(), foo.end(), [=](a x){cout << f(x) << " "; });
}
int main(){
vector<int> foo = {1,2,3,4,5};
printWith<int, int>(foo, [](int x) {return x + 1;});
std::cout << '\n';
return 0;
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,隐式转换在模板参数推导方面不能很好地发挥作用:正如您所看到的,我必须在调用中指定模板参数printWith.
另一种选择是使用std::function.这也有助于最小化模板实例化的数量,甚至对于具有lambda-capture的lambda表达式也有效,但是模板参数推导具有相同的问题:
#include <algorithm>
#include <functional>
#include <iostream>
#include <vector>
using namespace std;
template <typename a, typename b>
void printWith(const vector<a>& foo, std::function<b(a)> f){
for_each(foo.begin(), foo.end(), [&](a x){cout << f(x) << " "; });
}
int main(){
vector<int> foo = {1,2,3,4,5};
int y = 1;
printWith<int, int>(foo, [&](int x) { return x + y; });
std::cout << '\n';
return 0;
}
Run Code Online (Sandbox Code Playgroud)
您遇到问题的原因是因为您正在尝试使用某个功能.自由函数具有特定表示(作为函数指针),其不能与任何类型的函数对象互换.应避免使用函数指针(基本上就是这里).您需要使用模板指定的类型直接获取函数对象.
template <typename a, typename Func>
void printWith(vector<a> foo, Func func){
for_each(foo.begin(), foo.end(), [&](a x){cout << func(x) << " "; });
}
Run Code Online (Sandbox Code Playgroud)
或者,采用多态函数对象,如std::function.
template<typename a>
void printWith(vector<a> foo, std::function<string(const a&)> func) {
for_each(foo.begin(), foo.end(), [&](a x) { cout << func(x) << " "; });
}
Run Code Online (Sandbox Code Playgroud)