Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accept and return lambda (lock wrapper)

Tags:

c++

c++11

I want to accept any lambda, so that it can perform some operation safely under the lock_guard and then return anything, but using as shown below throws an error:

#include <iostream>
#include <functional>
#include <mutex>
#include <memory>

class Test {
    public:
        template<typename Ret>
        Ret DoLocked(std::function<Ret(Test&)> func) {
            std::lock_guard<std::mutex> lock(*mtx);
            return func(*this);
        }
    private:
        std::unique_ptr<std::mutex> mtx = std::make_unique<std::mutex>();
};

int main() {
    Test a;
    a.DoLocked([](Test &s) {
        std::cout << "in do locked" << std::endl;
    });

    return 0;
}
[build] /some-path/test.cc:21:6: error: no matching function for call to ‘Test::DoLocked(main()::<lambda(Test&)>)’
[build]    21 |     });
[build]       |      ^
[build] /some-path/test.cc:9:13: note: candidate: ‘template<class Ret> Ret Test::DoLocked(std::function<Ret(Test&)>)’
[build]     9 |         Ret DoLocked(std::function<Ret(Test&)> func) {
[build]       |             ^~~~~~~~
[build] /some-path/test.cc:9:13: note:   template argument deduction/substitution failed:
[build] /some-path/test.cc:21:6: note:   ‘main()::<lambda(Test&)>’ is not derived from ‘std::function<Ret(Test&)>’
[build]    21 |     });```
like image 479
t348575 Avatar asked Jun 20 '26 07:06

t348575


1 Answers

This is easily solved by getting rid of std::function and making the function parameter a template parameter. That would look like

template<typename Func>
auto DoLocked(Func func) -> decltype(func(*this)) {
    std::lock_guard<std::mutex> lock(*mtx);
    return func(*this);
}

The reason it doesn't work with the std::function is that a lambda expression does not create a std::function. It creates a object of an unnamed class type that has an operator() defined with the body of the lambda expression. Because of this, template deduction fails as it is expecting a std::function but that is not what is being provided.

like image 135
NathanOliver Avatar answered Jun 22 '26 21:06

NathanOliver



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!