The best I could get the fully general version is still pretty obtuse though:
// std doesn't have a template version of placeholders::_1, _2, etc., so we need to
// define our own.
template <int I> struct placeholder{};
template<>
template<int I>
struct std::is_placeholder<placeholder<I>> : std::integral_constant<int, I> {};
// flip must be an object so that the function type can be deduced without needing
// to explicitly specify its parameters' types.
template<typename F>
struct flip {
const F f;
// operator() deduces the argument types when the flip object is called, but really
// all we need to know is the number of arguments.
template<typename... Args>
constexpr auto operator()(Args... args) {
return bind_reversed(std::make_integer_sequence<int, sizeof...(Args)>{})(args...);
}
private:
// a helper function is needed to deduce a sequence of integers so we can bind all
// the placeholder values.
template<int... Is>
constexpr auto bind_reversed(std::integer_sequence<int, Is...>) {
return std::bind(f, placeholder<sizeof...(Is) - Is>{}...);
}
};