高阶函数和C++ 0x中的lambdas的问题

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.我该如何工作?

Mik*_*kov 6

以下适用于我:

#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)


Pup*_*ppy 5

您遇到问题的原因是因为您正在尝试使用某个功能.自由函数具有特定表示(作为函数指针),其不能与任何类型的函数对象互换.应避免使用函数指针(基本上就是这里).您需要使用模板指定的类型直接获取函数对象.

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)