Обернуть функцию N-arg в другую функцию - PullRequest
2 голосов
/ 16 февраля 2020

У меня есть функция, которая выполняет другую функцию в рабочем потоке:

void run_in_worker_thread( std::function< void( ) > proc )

Теперь я хотел бы реализовать функцию schedule () , которая принимает pro c ( ) функция в качестве аргумента и возвращает функцию, которая выполняет pro c () в рабочем потоке через run_in_worker_thread () .

Вот моя реализация:

#include <iostream>
#include <functional>

using namespace std;

class Test
{
  public:
    void run_in_worker_thread( std::function< void( ) > proc )
    {
            std::cout << "execute in worker thread\n";
            proc();
    }

    template < class... TArgs >
    std::function< void( TArgs... ) >
    schedule( std::function< void( TArgs... ) > proc )
    {
        std::function< void( TArgs... ) > f
                = [this, proc]( TArgs... args ) { run_in_worker_thread( [=]( ) { proc( args... ); } ); };
        return f;
    }  
};

int main()
{
    Test test;
    std::function<void(int, int)> my_funciton = 
         [](int a, int b) {std::cout << "got " << a << " and " << b << "\n";};
    auto f2 = test.schedule( my_funciton );
    f2(1, 2);
    return 0;
}

Проблема в том, что мой schedule () требует std :: function в качестве аргумента. Например, следующий вызов приводит к ошибке компиляции:

    auto my_funciton = [](int a, int b) {std::cout << "got " << a << " and " << b << "\n";};
    auto f2 = test.schedule( my_funciton );

1 Ответ

0 голосов
/ 16 февраля 2020

Проблема в том, что std::function - это оболочка полиморфного c вокруг вызываемого объекта. Лямбды не std::function с. Также как строковые литералы не std::string с. В первом примере вы делаете это:

std::function<void(int, int)> my_funciton = 
     [](int a, int b) {std::cout << "got " << a << " and " << b << "\n";};

Вы строите std::function из лямбды. Функция schedule способна без проблем определить сигнатуру функции.

Во втором примере вы сделаете следующее:

auto my_funciton = [](int a, int b) {std::cout << "got " << a << " and " << b << "\n";};

Тогда вы получите ошибку, потому что std::function<void (Args...)> не может быть сопоставлено с лямбда Решение этой проблемы - позволить schedule принимать любой вызываемый объект, а не только std::function.

template <typename Func>
auto schedule(Func proc) {
  return [this, proc](auto... args) {
    run_in_worker_thread([=]() {
      proc(args...);
    });
  };
}
...