This wraps a std::function
in a lambda that ignores any extra args:
template<class R, class...Args>
auto ignore_extra_args( std::function<R(Args...)> f ) {
return [f = std::move(f)](Args...args, auto&&...)->R{
return f(std::forward<Args>(args)...);
};
}
it gets trickier if we don't want that needless layer of type erasure.
You need to find the longest prefix of Args...
which you can invoke a given object f
with, then invoke f
with it. This involves some tricky metaprogramming.
It is far easier if you ask the caller to pass in a signature:
template<class Sig>
struct ignore_extra_args_helper;
template<class R, class...Args>
struct ignore_extra_args_helper<R(Args...)> {
template<class F>
auto operator()( F&& f ) {
return [f = std::forward<F>(f)](Args...args, auto&&...)->R{
return f(std::forward<Args>(args)...);
};
}
};
template<class Sig, class F>
auto ignore_extra_args( F&& f ) {
return ignore_extra_args_helper<Sig>{}(std::forward<F>(f));
}
which saves on possible overhead.
template<class F, decltype(std::declval<F const&>()(1,1))* =nullptr>
void add(F&& f) {
m.push_back(std::forward<F>(f));
}
template<class F, class...Unused>
void add(F&& f, Unused&&...) {
add( ignore_extra_args<void(int)>(std::forward<F>(f)) );
}
live example