Как передать метод и вызвать его с переменным количеством аргументов

у меня урок CallProtectorэто должно вызывать метод с переменным количеством аргументов, которые предполагают защиту вызова через мьютекс, но я не могу понять, как передать метод объекта с их аргументами. Вот что у меня есть до сих пор:

      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;
};

Я пытаюсь использовать это следующим образом:

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

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

    return 0;
}

Но у меня ошибка компиляции, говорящая

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

Ценю любую помощь, заранее спасибо.

2 ответа

Следующее может сработать для вас:

      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;
};

а затем используйте его как:

      Car alfaRomeo;
CallProtector callProtector;

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

РЕДАКТИРОВАТЬ

Или это тоже сработает:

      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)...);
}

а потом

      callProtector.callProtectedMethod(&Car::updateEngine, alfaRomeo, 10);

Начиная с С++ 17 вы можете использовать std::invoke, просто перенаправив ему все аргументы:

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

также, если вы хотите вызвать функцию-член в экземпляре автомобиля, вам нужно передать указатель на объект.

Полная демонстрация

Другие вопросы по тегам