2

I have class CallProtector that is supposed to call method with variable number of arguments which suppose to protect call via mutex, but I can't figure out how could I pass object's method with their arguments. Here what I have so far:

class CallProtector
{
public:

    template<typename F, typename ...Args>
    void callProtectedMethod(F& lambda, Args... args)
    {
        std::lock_guard<std::mutex> guard(m_guard);
        lambda(args);
    }

private:
    std::mutex m_guard;
};

I am trying to use it this way:

class Car
{
public:
    void updateEngine(int engineModelType) {}
};

int main()
{
    Car alfaRomeo;
    CallProtector callProtector;
    callProtector.callProtectedMethod(&Car::updateEngine, 10);

    return 0;
}

But I have compilation error saying

no instance of function template "CallProtector::callProtectedMethod" matches the argument list

Appreciate any help, thanks in advance.

2 Answers 2

1

Following might work for you:

class CallProtector
{
public:

    template<typename F, typename ...Args>
    void callProtectedMethod(F&& func, Args&&... args)
    {
        std::lock_guard<std::mutex> guard(m_guard);
        func(std::forward<Args>(args)...);
    }

private:
    std::mutex m_guard;
};

and then use it like:

Car alfaRomeo;
CallProtector callProtector;

auto updateEngine = std::bind(&Car::updateEngine, &alfaRomeo, std::placeholders::_1); 
callProtector.callProtectedMethod(updateEngine, 10);

EDIT

Or this would work too:

template<typename F, typename ...Args>
void callProtectedMethod(F&& func, Args&&... args)
{
    std::lock_guard<std::mutex> guard(m_guard);
    std::invoke(std::forward<F>(func), std::forward<Args>(args)...);
}

and then

callProtector.callProtectedMethod(&Car::updateEngine, alfaRomeo, 10);
Sign up to request clarification or add additional context in comments.

4 Comments

It is not working for me, says: 'term does not evaluate to a function taking 1 argument'. But we could not just forward all the arguments to the std::invoke? Is that any reason for that? It suppose to be very simple, but I really can't figure out.
what term? i think you are not showing us all the code. It works here which is msvc
Thanks, yes, my mistake this code works. But could we avoid doing bind and forward all the arguments?
I used this code to make it actually work: std::invoke(std::forward<F>(func), std::forward<Args>(args)...);
1

Since C++17 you can use std::invoke, just forwarding all arguments to it:

template<typename ...Args>
void callProtectedMethod(Args&&... args)
{
    std::lock_guard<std::mutex> guard(m_guard);
    std::invoke(std::forward<Args>(args)...);
}

also if you want to call member function on Car instance, you have to pass pointer to object.

Full demo

3 Comments

Thank you, but it is not working for me. Compile error says that: 'invoke' no matching overloaded function found. I am using visual studio 2019 with c++ 17. Also could we do the same with c++ 14?
@Oleg Why not to make callProtectedMethod as function accepting any callable object ? Demo, passed callable can be created as closure or result of std::bind function - there is no problem with passing arguments, just call function with protection of mutex.
I have to use different objects and pass pointer to it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.