Если я правильно понял, вы просто хотите сохранить функцию и набор аргументов, чтобы они могли быть вызваны позже. Это именно то, что делает std::bind
(во всяком случае, самое простое, что он делает). На самом деле, вы могли бы просто использовать std::bind
прямо вместо вашего MapFun
:
auto func1 = std::bind(userFun1, data, 3, 4);
auto func2 = std::bind(userFun2, data, 1, 2, "algorithm");
// ... and later,
func1();
func2();
Обратите внимание на auto
в этих: вы не можете (переносимо) записать тип любого объекта, возвращаемого std::bind
, и эти два примера объекта будут иметь разные типы. Но оба из них неявно преобразуются в общий тип std::function<void()>
. Вы можете хранить кучу std::function<void()>
объектов практически в любом типе контейнера, который вы хотите использовать позже:
std::map<unsigned int, std::function<void()>> func_map;
func_map[0] = std::bind(userFun1, data, 3, 4);
func_map[1] = std::bind(userFun2, data, 1, 2, "algorithm");
// ...
auto func_iter = func_map.find(key);
if (func_iter != func_map.end() && func_iter->second) {
(func_iter->second)();
}
Конечно, если вы хотите использовать свое имя функции и / или если вам нужен явный общий тип возврата для правильной работы с другими шаблонами или чем-то еще, вы можете просто обернуть std::bind
:
template <class F, class... Args>
std::function<void()> MapFun(F&& f, Args&&... args) {
return std::bind<void>(std::forward<F>(f), std::forward<Args>(args)...);
}
Или, если ваш MapFun
должен хранить вызываемый объект внутри некоторого контейнера члена класса или чего-то еще, а не просто создавать и возвращать один (это не ясно), он, конечно, может сделать это с помощью std::bind
и затем добавить результат для любого контейнера.