Универсальный вызов функции С++

Я хочу реализовать функцию caller, которая работает так же, как конструктор thread. Например

std::thread second (bar,0);

запустит поток, который вызывает bar с единственным аргументом 0. Я хотел бы сделать то же самое, но я не знаю, как это сделать.

Например, данный:

void myFunc(int a){
    cout << a << endl;
}

Я бы хотел:

int main() {
    caller(myFunc,12);
}

для вызова myFunc с параметром 12.

Ответ 1

std::bind сделает вызываемый объект из любого вызываемого объекта с произвольным набором параметров, как это делает конструктор thread. Поэтому просто оберните это в функцию, которая его вызывает:

template <typename... Args>
auto caller(Args &&... args) {
    return std::bind(std::forward<Args>(args)...)();
}

Обратите внимание, что для типа возвращаемого типа auto требуется С++ 14 или новее. Для С++ 11 вам нужно либо вернуть void, либо указать тип:

auto caller(Args &&... args) 
    -> decltype(std::bind(std::forward<Args>(args)...)())

Ответ 2

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

template <typename Function, typename Arg>
void call_with_one(Function&& f, Arg&& arg) {
    f(std::forward<Arg>(arg));
}

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

template <typename Function, typename... Arg>
void call_with_any(Function f, Arg&&... args) {
    f(std::forward<Arg>(args)...);
}

Или действительно f также должен быть ссылкой на пересылку:

template <typename Function, typename... Arg>
void call_with_any(Function&& f, Arg&&... args) {
    std::forward<Function>(f)(std::forward<Arg>(args)...);
}

Обратите внимание, что это будет работать только с функциями и объектами, которые реализуют operator(). Если f является указателем на член, это не сработает - вам придется вместо этого использовать std::bind в качестве Майка Сеймура.