This may be a naive question but here it goes anyway :
Suppose I have a class like this :
class func {
public:
int operator()(int it) const { return it + 21; }
};
As it's clear, a functor is defined in the above class, and if I do this :
func obj;
int capture = obj(9);
cout << capture << endl;
The result will be 30, as is obvious. But let's suppose I use STL's std::transform
to transform one container using the values of another container according to the functor defined above:
vector<int> v, vi;
v.push_back(1);
v.push_back(2);
vi.resize(v.size());
I follow the below syntax, where I'm invoking the functor directly using the class-name, and also, no argument is passed to the functor (which it requires according to the definition) :
std::transform(v.begin(), v.end(), vi.begin(), func());
This works perfectly. Why does this happen? Despite not using an instance of func
and also without passing an argument (which is the element of the first container apparently), why does this work?
Also, if I use an instance of func
, with an argument as I did above, it causes a compilation error.
func instance;
std::transform(v.begin(), v.end(), vi.begin(), instance());
How to use a functor properly in std::transform/std::for_each
? Why is there a difference in the way the functor method is invoked?
Also, from this answer on functors, we have the following piece of code :
// this is a functor
struct add_x {
add_x(int x) : x(x) {}
int operator()(int y) const { return x + y; }
private:
int x;
};
std::vector<int> in; // assume this contains a bunch of values)
std::vector<int> out(in.size());
// Pass a functor to std::transform, which calls the functor on every element
// in the input sequence, and stores the result to the output sequence
std::transform(in.begin(), in.end(), out.begin(), add_x(1));
The answer states that add_x(1)
acts a functor here (and not an instance), how is it an instance in the above example I gave?
std::transform(v.begin(), v.end(), vi.begin(), lambda_function());
// ^^^^^^^^^^^^^^^^^
That isn't invoking lambda_function::operator()
, it is just creating a temporary instance of lambda_function
. Inside std::transform
, this object will have its operator()
called iteratively with the contents of v
as arguments.
It's more obvious what is happening if you use C++11's braced initialization:
std::transform(v.begin(), v.end(), vi.begin(), lambda_function{});
Or perhaps if you consider this:
lambda_function()(0);
// ^^ creates instance
// ^^^ calls operator()
Regarding your second example:
std::transform(in.begin(), in.end(), out.begin(), add_x(1));
// ^^^^^^^^
This again creates a temporary instance of add_x
, but instead of calling the default constructor, it calls the add_x(int x);
constructor. This initialises some state in the function object so that when operator()
is called inside std::transform
, it adds the given number.