Should I pass a lambda by const reference.

前端 未结 3 1849
我寻月下人不归
我寻月下人不归 2020-12-29 09:24

Typically I use the following pattern when accepting a lambda as an argument to a function (A template class passed-by-value):

template 

        
3条回答
  •  无人及你
    2020-12-29 10:26

    If you pass by value you will copy the closure object (assuming you don't define the lambda inline, in which case it will be moved). This might be undesirable if the state is expensive to copy, and will fail to compile if the state is not copyable.

    template 
    void higherOrderFunction(Function f);
    
    std::unique_ptr p;
    auto l = [p = std::move(p)] {}; // C++14 lambda with init capture
    higherOrderFunction(l);         // doesn't compile because l is non-copyable 
                                    // due to unique_ptr member
    higherOrderFunction([p = std::move(p)] {}); // this still works, the closure object is moved
    

    If you pass by const reference, then you cannot pass a mutable lambda that modifies its data members as the argument to higherOrderFunction() because a mutable lambda has a non-const operator(), and you cannot invoke that on a const object.

    template 
    void higherOrderFunction(Function const& f);
    
    int i = 0;
    higherOrderFunction([=]() mutable { i = 0; }); // will not compile
    

    The best option is to use a forwarding reference. Then higherOrderFunction can accept either lvalues or rvalues that the caller passes.

    template 
    void higherOrderFunction(Function&& f) {
         std::forward(f)();
    }
    

    This allows the simple cases as well as the ones mentioned above to compile. For a discussion of why std::forward should be used, see this answer.

    Live demo

提交回复
热议问题