Last active
March 3, 2016 10:32
-
-
Save vmrob/c177309d66a3989f4d85 to your computer and use it in GitHub Desktop.
Revisions
-
vmrob revised this gist
Mar 3, 2016 . 1 changed file with 28 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -173,6 +173,28 @@ constexpr auto forward_tuple(F&& f, std::tuple<Args...>&& args) { ); } template <typename F, typename... Args> class bound_function { public: bound_function(F f, Args... args) : _f(std::move(f)) , _args(std::forward<Args>(args)...) {} auto operator()(){ return forward_tuple(std::move(_f), std::move(_args)); } private: F _f; std::tuple<Args...> _args; }; template <typename... Args> auto bind(Args&&... args) { return bound_function<Args...>(std::forward<Args>(args)...); } template <typename T> struct Vector2 { void setX(T v) { x = v; } @@ -186,13 +208,17 @@ struct Vector2 { using Vector2f = Vector2<float>; #include <cstdio> 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()); } -
vmrob created this gist
Mar 3, 2016 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,198 @@ #include <utility> #include <tuple> #include <type_traits> namespace meta { // detects callable objects, not functions // http://stackoverflow.com/questions/15393938/find-out-if-a-c-object-is-callable template<typename T> class is_callable_object { private: using yes = char(&)[1]; using no = char(&)[2]; struct Fallback { void operator()(); }; struct Derived : T, Fallback { }; template<typename U, U> struct Check; template<typename> static yes test(...); template<typename C> static no test(Check<void (Fallback::*)(), &C::operator()>*); public: static const bool value = sizeof(test<Derived>(0)) == sizeof(yes); }; template <typename T> static constexpr auto is_callable_object_v = is_callable_object<T>::value; // function traits inline namespace detail { template <typename ReturnType, typename ClassType, typename ... Args> struct mem_function_traits { static constexpr auto arity = sizeof...(Args); using result_type = ReturnType; using class_type = ClassType; static constexpr auto valid = true; template <size_t i> struct arg { using type = std::tuple_element_t<i, std::tuple<Args...>>; }; template <size_t i> using arg_t = typename arg<i>::type; }; template <typename ReturnType, typename ... Args> struct reg_function_traits { static constexpr auto arity = sizeof...(Args); using result_type = ReturnType; static constexpr auto valid = true; template <size_t i> struct arg { using type = decltype(std::get<i>(std::tuple<Args...>())); }; template <size_t i> using arg_t = typename arg<i>::type; }; } // namespace detail // no types defined template <typename T, typename = void, typename = void> struct function_traits { static constexpr auto valid = false; }; // generic functions template <typename T> struct function_traits<T, std::enable_if_t<std::is_class<T>::value>, std::enable_if_t<is_callable_object_v<T>>> : public function_traits<decltype(&T::operator())> { }; template <typename T> struct function_traits<T, std::enable_if_t<std::is_reference<T>::value>> : public function_traits<typename std::remove_reference_t<T>> { }; // const member functions template <typename ReturnType, typename ClassType, typename... Args> struct function_traits<ReturnType(ClassType::*)(Args...) const, std::enable_if_t<std::is_member_function_pointer<ReturnType(ClassType::*)(Args...)>::value>> : public mem_function_traits<ReturnType, ClassType, Args...> { }; // member functions template <typename ReturnType, typename ClassType, typename ... Args> struct function_traits<ReturnType(ClassType::*)(Args...), std::enable_if_t<std::is_member_function_pointer<ReturnType(ClassType::*)(Args...)>::value>> : public mem_function_traits<ReturnType, ClassType, Args...> { }; // regular functions template <typename ReturnType, typename ... Args> struct function_traits<ReturnType(Args...), std::enable_if_t<std::is_function<ReturnType(Args...)>::value>> : public reg_function_traits<ReturnType, Args...> { }; // is_callable template <typename T> struct is_callable : public std::integral_constant<bool, function_traits<T>::valid> {}; // result_of template <typename T> struct result_of { using type = std::result_of_t<T>; }; template <typename R, typename... Args> struct result_of<R(*)(Args...)> { using type = R; }; template <typename R, typename... Args> struct result_of<R(&)(Args...)> { using type = R; }; template <typename R, typename C, typename ... Args> struct result_of<R(C::*)(Args...)> { using type = R; }; template <typename R, typename C, typename ... Args> struct result_of<R(C::*)(Args...) const> { using type = R; }; } // namespace meta template <typename F, typename = void> struct forward_tuple_impl { template <typename... TupleArgs, size_t... I, typename = void> auto operator()(F&& f, std::tuple<TupleArgs...>&& tuple, std::index_sequence<I...>) { return f(std::get<I>(std::forward<std::tuple<TupleArgs...>>(tuple))...); } }; template <typename F> struct forward_tuple_impl<F, std::enable_if_t<std::is_member_function_pointer<F>::value>> { template <typename ClassPtrType, typename... TupleArgs, size_t... I> auto operator()(F&& f, std::tuple<ClassPtrType, TupleArgs...>&& tuple, std::index_sequence<0, I...>) { static_assert( std::is_same<std::remove_cv_t<typename meta::function_traits<F>::class_type*>, std::remove_cv_t<ClassPtrType>>::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<I>(std::forward<std::tuple<ClassPtrType, TupleArgs...>>(tuple))...); } }; template<typename F, typename... Args> constexpr auto forward_tuple(F&& f, std::tuple<Args...>&& args) { return forward_tuple_impl<F>()( std::forward<F>(f), std::forward<std::tuple<Args...>>(args), std::index_sequence_for<Args...>{} ); } template <typename T> 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<float>; #include <iostream> int main() { Vector2f vec{0.0f, 2.0f}; forward_tuple(&Vector2f::setX, std::make_tuple(&vec, 3.0f)); printf("%f\n", vec.getX()); }