#include #include #include namespace meta { // detects callable objects, not functions // http://stackoverflow.com/questions/15393938/find-out-if-a-c-object-is-callable template class is_callable_object { private: using yes = char(&)[1]; using no = char(&)[2]; struct Fallback { void operator()(); }; struct Derived : T, Fallback { }; template struct Check; template static yes test(...); template static no test(Check*); public: static const bool value = sizeof(test(0)) == sizeof(yes); }; template static constexpr auto is_callable_object_v = is_callable_object::value; // function traits inline namespace detail { template struct mem_function_traits { static constexpr auto arity = sizeof...(Args); using result_type = ReturnType; using class_type = ClassType; static constexpr auto valid = true; template struct arg { using type = std::tuple_element_t>; }; template using arg_t = typename arg::type; }; template struct reg_function_traits { static constexpr auto arity = sizeof...(Args); using result_type = ReturnType; static constexpr auto valid = true; template struct arg { using type = decltype(std::get(std::tuple())); }; template using arg_t = typename arg::type; }; } // namespace detail // no types defined template struct function_traits { static constexpr auto valid = false; }; // generic functions template struct function_traits::value>, std::enable_if_t>> : public function_traits { }; template struct function_traits::value>> : public function_traits> { }; // const member functions template struct function_traits::value>> : public mem_function_traits { }; // member functions template struct function_traits::value>> : public mem_function_traits { }; // regular functions template struct function_traits::value>> : public reg_function_traits { }; // is_callable template struct is_callable : public std::integral_constant::valid> {}; // result_of template struct result_of { using type = std::result_of_t; }; template struct result_of { using type = R; }; template struct result_of { using type = R; }; template struct result_of { using type = R; }; template struct result_of { using type = R; }; } // namespace meta template struct forward_tuple_impl { template auto operator()(F&& f, std::tuple&& tuple, std::index_sequence) { return f(std::get(std::forward>(tuple))...); } }; template struct forward_tuple_impl::value>> { template auto operator()(F&& f, std::tuple&& tuple, std::index_sequence<0, I...>) { static_assert( std::is_same::class_type*>, std::remove_cv_t>::value, "First argument in parameter pack must be a pointer to an class with member function F"); return (std::get<0>(tuple)->*f)(std::get(std::forward>(tuple))...); } }; template constexpr auto forward_tuple(F&& f, std::tuple&& args) { return forward_tuple_impl()( std::forward(f), std::forward>(args), std::index_sequence_for{} ); } template class bound_function { public: bound_function(F f, Args... args) : _f(std::move(f)) , _args(std::forward(args)...) {} auto operator()(){ return forward_tuple(std::move(_f), std::move(_args)); } private: F _f; std::tuple _args; }; template auto bind(Args&&... args) { return bound_function(std::forward(args)...); } template struct Vector2 { void setX(T v) { x = v; } void setY(T v) { y = v; } T getX() { return x; } T getY() { return y; } T x; T y; }; using Vector2f = Vector2; #include int main() { Vector2f vec{0.0f, 2.0f}; auto f = bind(&Vector2f::setX, &vec, 3.0f); printf("%f\n", vec.getX()); f(); printf("%f\n", vec.getX()); }