Search code examples
c++c++11lambdamove

Move to lambda capture C++11


In my code I'm using Item 32 advice from Scott Meyers Effective Modern C++, where he explains how to move into the capture in C++11. The sample code works well.

class Some
{
public:
    void foo()
    {
        std::string s = "String";
        std::function<void()> lambda = std::bind([this](std::string& s) {
            bar(std::move(s));
        }, std::move(s));

        call(std::move(lambda));
    }

    void bar(std::string)
    {
        // Some code
    }

    void call(std::function<void()> func)
    {
        func();
    }
};

int main()
{
    Some().foo();
}

Then I tried to use move in the capture in more difficult way with parameters, but it doesn't work, there are some compilation errors. Please, help me to fix it. Code with error below. I've played with it, but couldn't find a solution. Is it possible to do it?

class Some
{
public:
    void foo()
    {
        std::string stringToMove = "String";

        std::function<void(std::string, int, int)> lambda =
            std::bind([this](std::string s, int i1, int i2, std::string& stringToMove) {
            bar(std::move(stringToMove), i1, i2);
        }, std::move(stringToMove));

        call(std::move(lambda));
    }

    void bar(std::string, int, int)
    {
        // Some code
    }

    void call(std::function<void(std::string, int, int)> func)
    {
        func(std::string(), 5, 5);
    }
};

int main()
{
    Some().foo();
}

Errors:

Severity Code Description Project File Line Suppression State Error C2672 'std::invoke': no matching overloaded function found drafts c:\program files (x86)\microsoft visual studio 14.0\vc\include\type_traits 1468

Severity Code Description Project File Line Suppression State Error C2893 Failed to specialize function template 'unknown-type std::invoke(_Callable &&,_Types &&...)' drafts c:\program files (x86)\microsoft visual studio 14.0\vc\include\type_traits 1468


Solution

  • std::bind requires of you to specify all the parameters. So those which should be passed to the resulting function object, need to be placeholders.

    std::function<void(std::string, int, int)> lambda =
                std::bind([this](std::string s, int i1, int i2, std::string& stringToMove) {
                bar(std::move(stringToMove), i1, i2);
            }, _1, _2, _3, std::move(stringToMove));