2017-10-11 79 views
0

this问题我对functors(函数对象)有了很好的理解;如何初始化并调用它们。我写了一些代码,使这个玩弄我自己的理解为什么在std :: transform中使用函数对象参数失败并且需要lambda表达式而不是

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表达式?另一个答案是做同样的事情,但它仍然会导致编译错误。这是为什么?

+9

这听起来像一个错字。 'poo(1)' - >'Foo(1)'。 –

+0

我认为这更多的是误导性的错误信息,使你错过了你引用了一些不存在的事实:'poo'。 –

+1

'poo(1)'是一个'int';如错误信息所示,它不是一个带1个参数的函数。 'Foo(1)'是一个带有'operator()'的函数对象,它接受一个'int'类型的单个参数。 –

回答

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在您的解决方法中进行了交换,并且实例的数量也发生了变化。

Foo poo(1); 

,只是发送到便便变换,不适用(1)调用:

1

如果添加了一个定义,它也可以。变换需要一个带有()运算符的对象来调用,并且单独声明它使得它更清楚它的范围。

+0

是啊定义'Foo poo(1)',然后传入变量'poo'。好主意。 – Mushy

相关问题