Option number 1
C ++ 11 basic solution by introducing an ignored parameter first ( DEMO 1 ):
template <typename Arg, typename R, typename... Args>
std::function<R(Arg, Args...)> add_ignored_arg(std::function<R(Args...)> f)
{
return [f] (Arg&& , Args&&... args) { return f(std::forward<Args>(args)...); };
}
Note: it std::forward<Args>(args) works correctly (although Args&&it is not a link to transfer), because it std::functionpasses arguments passed by value to rvalue values, while lvalue links fall in accordance with the rule: & &&→ &.
Option number 2
++ 14 , ( DEMO 2):
template <typename Arg, typename R, typename... Args>
std::function<R(Arg, Args...)> add_ignored_arg(std::function<R(Args...)> f)
{
return [f] (auto&& , auto&&... args) { return f(std::forward<decltype(args)>(args)...); };
}
№ 3
++ 11 , std::function ( DEMO 3):
template <std::size_t N, typename Arg, typename R, typename... Args, std::size_t... Before, std::size_t... After, typename Tuple = std::tuple<Args...>>
auto inject_param(index_sequence<Before...>, index_sequence<After...>)
-> std::function<R(typename std::tuple_element<Before, Tuple>::type..., Arg, typename std::tuple_element<N + After, Tuple>::type...)>;
template <std::size_t N, typename Arg, typename R, typename... Args, std::size_t... Before, std::size_t... After, typename Tuple = std::tuple<Args...>>
auto add_ignored_arg(std::function<R(Args...)> f, index_sequence<Before...>, index_sequence<After...>)
-> decltype(inject_param<N, Arg, R, Args...>(index_sequence<Before...>{}, index_sequence<After...>{}))
{
return [f] (typename std::tuple_element<Before, Tuple>::type&&... before
, Arg&&
, typename std::tuple_element<N + After, Tuple>::type&&... after)
{
return f(std::forward<typename std::tuple_element<Before, Tuple>::type>(before)...,
std::forward<typename std::tuple_element<N + After, Tuple>::type>(after)...);
};
}
template <std::size_t N, typename Arg, typename R, typename... Args, typename Tuple = std::tuple<Args...>>
auto add_ignored_arg(std::function<R(Args...)> f)
-> decltype(inject_param<N, Arg, R, Args...>(make_index_sequence<N>{}, make_index_sequence<sizeof...(Args) - N>{}))
{
return add_ignored_arg<N, Arg>(f, make_index_sequence<N>{}, make_index_sequence<sizeof...(Args) - N>{});
}
template <std::size_t N, typename Arg, typename R, typename... Args, typename Tuple = std::tuple<Args...>>
auto add_ignored_arg(R(*f)(Args...))
-> decltype(inject_param<N, Arg, R, Args...>(make_index_sequence<N>{}, make_index_sequence<sizeof...(Args) - N>{}))
{
return add_ignored_arg<N, Arg>(std::function<R(Args...)>(f), make_index_sequence<N>{}, make_index_sequence<sizeof...(Args) - N>{});
}
. index_sequence . , № 1.
№ 4
++ 14 , ( DEMO 4):
template <std::size_t N, typename Arg, typename R, typename... Args, std::size_t... Before, std::size_t... After, typename Tuple = std::tuple<Args...>>
auto add_ignored_arg(std::function<R(Args...)> f, std::index_sequence<Before...>, std::index_sequence<After...>)
-> std::function<R(typename std::tuple_element<Before, Tuple>::type..., Arg, typename std::tuple_element<N + After, Tuple>::type...)>
{
return [f] (auto&&... args)
{
auto t = std::forward_as_tuple(std::forward<decltype(args)>(args)...);
return f(static_cast<typename std::tuple_element<Before, decltype(t)>::type>(std::get<Before>(t))...,
static_cast<typename std::tuple_element<N + After + 1, decltype(t)>::type>(std::get<N + After + 1>(t))...);
};
}
template <std::size_t N, typename Arg, typename R, typename... Args, typename Tuple = std::tuple<Args...>>
auto add_ignored_arg(std::function<R(Args...)> f)
{
return add_ignored_arg<N, Arg>(f, std::make_index_sequence<N>{}, std::make_index_sequence<sizeof...(Args) - N>{});
}
template <std::size_t N, typename Arg, typename R, typename... Args, typename Tuple = std::tuple<Args...>>
auto add_ignored_arg(R(*f)(Args...))
{
return add_ignored_arg<N, Arg>(std::function<R(Args...)>(f), std::make_index_sequence<N>{}, std::make_index_sequence<sizeof...(Args) - N>{});
}
struct B {};
void foo(int i, char c, double d)
{
std::cout << i << " " << c << " " << d << std::endl;
}
void doSomething(std::function<void(int, char, B, double)> callback)
{
callback(123, 'A', B{}, 3.14f);
}
void myDoSomething(std::function<void(int, char, double)> callback)
{
doSomething(add_ignored_arg<2, B>(callback));
}
int main()
{
myDoSomething(&foo);
}
:
123 A 3.14