为什么在std :: transform中使用函数对象参数会失败并需要使用lambda表达式

时间:2017-10-11 20:20:27

标签: c++ c++11 lambda functor

this问题我对仿函数(函数对象)有了很好的理解;如何初始化和调用它们。为了我自己的理解,我写了一些代码来解决这个问题

class Foo
{
private:
   int x;
public:
   Foo(int x) : x(x) {}
   int operator()(int y) { return x + y; }
};

Foo poo(50);

int a = poo(50);

std::cout << a;

std::vector<int> vec(10);
std::vector<int> pec(10);

std::transform(vec.begin(), vec.end(), vec.begin(), poo(1));

并收到以下编译错误

Severity    Code    Description Project File    Line    Suppression State
Error   C2064   term does not evaluate to a function taking 1 arguments 

我在上面的问题中查看了一些评论并尝试了一个lambda表达式

std::transform(vec.begin(), vec.end(), vec.begin(), [](Foo poo) {return poo(1); });

有效,但我不明白为什么使用std::transform(in.begin(), in.end(), out.begin(), add_x(1));的接受答案失败了。为什么我必须使用lambda表达式?另一个答案是做同样的事情,但它仍然会导致编译错误。那是为什么?

2 个答案:

答案 0 :(得分:3)

这段代码很好用。

#include <iostream>
#include <array>

class add_x
{
private:
   int x;

public:
   add_x(int x) : x(x) {}

   int operator()(int y) /* consider adding const here */
   { return x + y; }
};


int main()
{
    std::array<int, 5> input { 1, 4, 9, 16, 25 };
    std::array<int, 5> output;
    std::transform(begin(input), end(input), begin(output), add_x(1));
    for ( auto& val : output ) std::cout << val << "\n";
}

但是,调用const成员函数可能是一个好主意,因为它不会改变仿函数。这也可能使它适用于更多版本的标准库。

这个和你的lambda版本之间的区别在于,在这里,常量1被传递给构造函数以创建一个仿函数对象,并且数据被顺序传递给该单个仿函数实例的运算符。在lambda中,通过调用转换构造函数从每个数据创建一个新对象,然后将常量传递给运算符。也就是说,您的变通方法会交换xy,并且还会更改实例数。

答案 1 :(得分:1)

如果添加定义,它也有效:

[{
  slug: "brand",
  ...,
  domain: {
     production: 'www.domain.com'
  }
 }, {
  slug: "brand1",
  ...,
  domain: {
     production: 'www.domain1.com'
 }]

只需将poo发送到transform,而不进行(1)调用。变换需要一个带有()运算符的对象来调用,并单独声明它使它的范围更加清晰。