Reputation: 207
I'm having a little trouble using a function object create an instance of std::function. (My environment is C++ 11 using Visual Studio 2015.)
First, I have a class that is used in the argument list of my function object. Here is a simplified version that illustrates the essential point.
class X
{
public:
void zz(int a) const
{
std::cout << "X:zz, a = " << a << "." << std::endl;
}
};
Then here is the function object, which uses X in its operator() method.
class Y
{
public:
void operator()(const X& x)
{
x.zz(17);
}
};
Now, I'd like to wrap an instance of Y in a std::function. The type of the function is void(const X&), a void function taking a const reference to X as an argument. The method Y:operator() has this signature.
void test_it
{
X my_x;
Y my_y;
std::function<void(const X&)> f1(my_y);
f1(my_x); // OK
std::function<void(const X&)> f2(Y());
f2(my_x); // cannot convert argument 1 from X to Y
std::function<void(const X&)> f3(Y);
f3(my_x); // cannot convert argument 1 from X to Y
std::function<void(const X&)> f4(Y{});
f4(my_x); // OK
}
The first example, f1, creates an instance of Y, my_y, and creates f1 using this instance. This works fine. (The contents of Y get moved into the std::function in the std::function constructor.)
The second try, f2, constructs an instance of Y in the constructor for f2. When I try to invoke it with f2(my_x) the compiler complains that it cannot convert argument 1 (my_x) from an X to a Y.
The third try, f3, where I just name the function object class in the std::function construction of f3 fails in the same way as f2.
Finally, f4 works. In this one, I construct the function object Y using an empty initializer list.
Perhaps there is a simple explanation, but I cannot see why two of these use-cases don't compile. In particular f2, using Y(), and f4 using Y{}, seem virtually identical to me.
Upvotes: 3
Views: 1728
Reputation: 29013
For the second case, the expression Y()
is trying to define a function that returns a Y
and that takes no arguments, and passing that function as the argument. This is known as the most vexing parse.
For the third case, you cannot give a type instead of a function argument.
The correct way to pass a default constructed instance of Y
to std::function
is the 4th case.
Upvotes: 5