I have a bunch of functions which I want to use as functors (that is, use types instead of pass pointers to the functions, or any other kind of data).
Is there an elegant/idiomatic/standard way of doing this with the standard library, or the standard library + Boost? Perhaps using bind()
somehow?
Or should I go with something simplistic (well, kind of simplistic) such as:
template<typename Function, Function& F, typename... Parameters>
struct functor {
using function_type = Function;
using parameters_as_tuple_type = std::tuple<Parameters...>;
auto operator() (Parameters&&... params) ->
decltype(F(std::forward<Parameters>(params)...))
{
return F(std::forward<Parameters>(params)...);
}
};
Notes:
First, a concrete example for a fixed type.
int foo( int );
void foo( double );
struct foo_t {
template<class...Args>
auto operator()(Args&&...args)const
->decltype( foo( std::declval<Args>()... ) )
{ return ( foo( std::forward<Args>(args)... ) ); }
};
now foo_t
is an object that invokes the overloads of foo
via perfect forwarding.
To make it generic:
#define RETURNS(...) noexcept(noexcept(__VA_ARGS__)) -> decltype(__VA_ARGS__) { return __VA_ARGS__; }
#define OVERLOAD_SET_TYPE(...) \
struct { \
template<class...Args> \
auto operator()(Args&&...args)const \
RETURNS( __VA_ARGS__( std::forward<Args>(args)... ) ) \
}
so we can do
using foo_t = OVERLOAD_SET_TYPE(foo);
You cannot manipulate overload sets of a function as an object; the only way to do it is textually. Hence the macro.
This has all of the usual imperfections of perfect forwarding. There is no way to generically avoid those imperfections.