/*============================================================================= Copyright (c) 2011-2016 Bolero MURAKAMI https://github.com/bolero-MURAKAMI/Sprout Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) =============================================================================*/ #ifndef SPROUT_FUNCTIONAL_MEM_FN_HPP #define SPROUT_FUNCTIONAL_MEM_FN_HPP #include #include #include #include #include #include namespace sprout { // 20.8.10 member function adaptors namespace detail { template struct maybe_unary_or_binary_function {}; template struct maybe_unary_or_binary_function : public sprout::unary_function {}; template struct maybe_unary_or_binary_function : public sprout::binary_function {}; template struct mem_fn_const_or_non { public: typedef T const& type; }; template struct mem_fn_const_or_non { public: typedef T& type; }; } // namespace detail // // mem_fn_adaptor // template class mem_fn_adaptor; template class mem_fn_adaptor : public sprout::detail::maybe_unary_or_binary_function { public: typedef Res result_type; private: typedef Res (Class::*functor)(Args...); private: Res (Class::*pmf_)(Args...); private: template Res call(T& object, Class const volatile*, Args... args) const { return (object.*pmf_)(SPROUT_FORWARD(Args, args)...); } template Res call(T& ptr, void const volatile*, Args... args) const { return ((*ptr).*pmf_)(SPROUT_FORWARD(Args, args)...); } public: explicit SPROUT_CONSTEXPR mem_fn_adaptor(Res (Class::*pmf)(Args...)) : pmf_(pmf) {} Res operator()(Class& object, Args... args) const { return (object.*pmf_)(SPROUT_FORWARD(Args, args)...); } Res operator()(Class* object, Args... args) const { return (object->*pmf_)(SPROUT_FORWARD(Args, args)...); } template Res operator()(T& object, Args... args) const { return call(object, &object, SPROUT_FORWARD(Args, args)...); } }; template class mem_fn_adaptor : public sprout::detail::maybe_unary_or_binary_function { public: typedef Res result_type; private: typedef Res (Class::*functor)(Args...) const; private: Res (Class::*pmf_)(Args...) const; private: template SPROUT_CONSTEXPR Res call(T const& object, Class const volatile*, Args... args) const { return (object.*pmf_)(SPROUT_FORWARD(Args, args)...); } template SPROUT_CONSTEXPR Res call(T const& ptr, void const volatile*, Args... args) const { return ((*ptr).*pmf_)(SPROUT_FORWARD(Args, args)...); } public: explicit SPROUT_CONSTEXPR mem_fn_adaptor(Res (Class::*pmf)(Args...) const) : pmf_(pmf) {} SPROUT_CONSTEXPR Res operator()(Class const& object, Args... args) const { return (object.*pmf_)(SPROUT_FORWARD(Args, args)...); } SPROUT_CONSTEXPR Res operator()(Class const* object, Args... args) const { return (object->*pmf_)(SPROUT_FORWARD(Args, args)...); } template SPROUT_CONSTEXPR Res operator()(T const& object, Args... args) const { return call(object, &object, SPROUT_FORWARD(Args, args)...); } }; template class mem_fn_adaptor : public sprout::detail::maybe_unary_or_binary_function { public: typedef Res result_type; private: typedef Res (Class::*functor)(Args...) volatile; private: Res (Class::*pmf_)(Args...) volatile; private: template Res call(T& object, Class const volatile*, Args... args) const { return (object.*pmf_)(SPROUT_FORWARD(Args, args)...); } template Res call(T& ptr, void const volatile*, Args... args) const { return ((*ptr).*pmf_)(SPROUT_FORWARD(Args, args)...); } public: explicit SPROUT_CONSTEXPR mem_fn_adaptor(Res (Class::*pmf)(Args...) volatile) : pmf_(pmf) {} Res operator()(Class volatile& object, Args... args) const { return (object.*pmf_)(SPROUT_FORWARD(Args, args)...); } Res operator()(Class volatile* object, Args... args) const { return (object->*pmf_)(SPROUT_FORWARD(Args, args)...); } template Res operator()(T& object, Args... args) const { return call(object, &object, SPROUT_FORWARD(Args, args)...); } }; template class mem_fn_adaptor : public sprout::detail::maybe_unary_or_binary_function { public: typedef Res result_type; private: typedef Res (Class::*functor)(Args...) const volatile; private: Res (Class::*pmf_)(Args...) const volatile; private: template SPROUT_CONSTEXPR Res call(T const& object, Class const volatile*, Args... args) const { return (object.*pmf_)(SPROUT_FORWARD(Args, args)...); } template SPROUT_CONSTEXPR Res call(T const& ptr, void const volatile*, Args... args) const { return ((*ptr).*pmf_)(SPROUT_FORWARD(Args, args)...); } public: explicit SPROUT_CONSTEXPR mem_fn_adaptor(Res (Class::*pmf)(Args...) const volatile) : pmf_(pmf) {} SPROUT_CONSTEXPR Res operator()(Class const volatile& object, Args... args) const { return (object.*pmf_)(SPROUT_FORWARD(Args, args)...); } SPROUT_CONSTEXPR Res operator()(Class const volatile* object, Args... args) const { return (object->*pmf_)(SPROUT_FORWARD(Args, args)...); } template SPROUT_CONSTEXPR Res operator()(T const& object, Args... args) const { return call(object, &object, SPROUT_FORWARD(Args, args)...); } }; template class mem_fn_adaptor { private: typedef char one; struct two { char v[2]; }; private: template static T& get_ref(); template static one check_const(T&, Class*); template static one check_const(T&, Up* const*); template static two check_const(T&, Up const* const*); template static two check_const(T&, Class const*); template static two check_const(T&, void const volatile*); public: template struct result_type : public sprout::detail::mem_fn_const_or_non< Res, (sizeof(two) == sizeof(check_const(get_ref(), typename sprout::identity::type()))) > {}; template struct result; template struct result : public result_type {}; template struct result : public result_type {}; private: Res Class::* pm_; private: template Res& call(T& object, Class*) const { return object.*pm_; } template Res& call(T& object, Up* const*) const { return (*object).*pm_; } template const Res& call(T& object, Up const* const*) const { return (*object).*pm_; } template Res const& call(T& object, Class const*) const { return object.*pm_; } template const Res& call(T& ptr, void const volatile*) const { return (*ptr).*pm_; } public: explicit SPROUT_CONSTEXPR mem_fn_adaptor(Res Class::* pm) : pm_(pm) {} Res& operator()(Class& object) const { return object.*pm_; } SPROUT_CONSTEXPR Res const& operator()(Class const& object) const { return object.*pm_; } Res& operator()(Class* object) const { return object->*pm_; } SPROUT_CONSTEXPR Res const& operator()(Class const* object) const { return object->*pm_; } template typename result_type::type operator()(T& unknown) const { return call(unknown, &unknown); } }; // // mem_fn // template inline SPROUT_CONSTEXPR sprout::mem_fn_adaptor mem_fn(T Class::* pm) { return sprout::mem_fn_adaptor(pm); } } // namespace sprout #endif // #ifndef SPROUT_FUNCTIONAL_MEM_FN_HPP