template<class R, class P>
void doSomethingElse(std::function<R(P)> f) {
f(P{});
}
Будет работать, но это работает, только если вы передадите std::function
функции, и у этой функции будет один не пустой параметр. Это своего рода ограничение, хотя. Вы можете использовать
template<class R, class... Args, class... Ts>
void doSomethingElse(std::function<R(Args...)> f, Ts&&... args) {
f(std::forward<Args>(args)...);
}
Который примет любые std::function
и аргументы для него и вызовет их, как если бы вы сделали это на сайте вызовов. Это все еще ограничивает, потому что сайт вызова требует, чтобы вы использовали std::function
, поэтому вы не можете передать ему ничего неявно конвертируемого в std::function
.
С C ++ 17 и вычет аргумента шаблона класса (CTAD) это больше не проблема. Мы можем создать перегрузку, которая принимает любой тип, а затем с помощью CTAD создать std :: function для заполнения типов для нас. Это будет выглядеть как
template<class Func, class... Args>
void doSomethingElse(Func&& f, Args&&... args) {
doSomethingElse(std::function{std::forward<Func>(f)}, std::forward<Args>(args)...);
}
template<class R, class... Args, class... Ts>
void doSomethingElse(std::function<R(Args...)> f, Ts&&... args) {
f(std::forward<Args>(args)...);
}
И теперь все, что не является std::function
, перейдет к void doSomethingElse(Func&& f, Args&&... args)
, преобразуется в std::function
и будет передано void doSomethingElse(std::function<R(Args...)> f, Args&&... args)
, чтобы вы могли использовать тип возвращаемого значения и тип аргумента (ов) ( s) там.