Is there a way to partially bind the first/last n arguments of a callable object (e.g. function) without explicitly specifying the rest of the arguments?
std::bind()
seems to require that all the arguments are be bound, those that are to be left should be bound to std::placeholders::_1
,_2
,_3
etc.
Is it possible to write a bind_first()
/bind_last()
for partial binding starting from the first/last argument and that automagically inserts the placeholders for any remaining unbound arguments in their original order in their the original position?
The Partially applied functions are the functions which are not applied on all the arguments defined by the stated function i.e, while invoking a function, we can supply some of the arguments and the left arguments are supplied when required.
What is a Partial Function? Using partial functions is a component of metaprogramming in Python, a concept that refers to a programmer writing code that manipulates code. You can think of a partial function as an extension of another specified function.
bind is a method on the prototype of all functions in JavaScript. It allows you to create a new function from an existing function, change the new function's this context, and provide any arguments you want the new function to be called with.
From HaskellWiki. A partial function is a function that is not defined for all possible arguments of the specified type. Examples in the Haskell standard library are: head , tail : undefined for empty lists. (!!) : undefined if the index is at least as big as the list length.
Neither Boost nor the standard library bind
fill in the blanks automatically. You could write such a gadget yourself if you have a rainy evening to fill; here's an example for trailing arguments of a plain function only:
#include <tuple>
#include <type_traits>
#include <utility>
template <typename F, typename ...Args> struct trailing_binder;
template <typename R, typename ...Frgs, typename ...Args>
struct trailing_binder<R(Frgs...), Args...>
{
template <typename ...Brgs>
trailing_binder(R (*f)(Frgs...), Brgs &&... brgs)
: the_function(f)
, the_args(std::forward<Brgs>(brgs)...)
{ }
template <unsigned int ...I> struct intlist {};
template <typename ...Brgs>
typename std::enable_if<sizeof...(Brgs) + sizeof...(Args) == sizeof...(Frgs), R>::type
operator()(Brgs &&... brgs)
{
return unwrap(std::integral_constant<bool, 0 == sizeof...(Args)>(),
intlist<>(),
std::forward<Brgs>(brgs)...);
}
private:
template <unsigned int ...I, typename ...Brgs>
R unwrap(std::false_type, intlist<I...>, Brgs &&... brgs)
{
return unwrap(std::integral_constant<bool, sizeof...(I) + 1 == sizeof...(Args)>(),
intlist<I..., sizeof...(I)>(),
std::forward<Brgs>(brgs)...);
}
template <unsigned int ...I, typename ...Brgs>
R unwrap(std::true_type, intlist<I...>, Brgs &&... brgs)
{
return the_function(std::get<I>(the_args)..., std::forward<Brgs>(brgs)...);
}
R (*the_function)(Frgs...);
std::tuple<Args...> the_args;
};
template <typename R, typename ...Args, typename ...Frgs>
trailing_binder<R(Frgs...), Args...> trailing_bind(R (*f)(Frgs...), Args &&... args)
{
return trailing_binder<R(Frgs...), typename std::decay<Args>::type...>(f, std::forward<Args>(args)...);
}
Usage:
int f(int a, int b, int c, int d) { return a + b + c + d; }
int main()
{
auto b = trailing_bind(f, 1);
return b(3, 8, 13);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With