cha
cha

Reputation: 207

Passing a function object to std::function

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

Answers (1)

Fran&#231;ois Andrieux
Fran&#231;ois Andrieux

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

Related Questions