/*============================================================================= Copyright (c) 2011-2013 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_REF_HPP #define SPROUT_FUNCTIONAL_REF_HPP #include #include #include #include #include #include #include #include #include namespace sprout { // 20.8.3 reference_wrapper namespace detail { template struct reference_wrapper_base_impl; template struct reference_wrapper_base_impl : public sprout::weak_result_type {}; template struct reference_wrapper_base_impl : public sprout::weak_result_type { public: typedef typename T::argument_type argument_type; }; template struct reference_wrapper_base_impl : public sprout::weak_result_type { public: typedef typename T::first_argument_type first_argument_type; typedef typename T::second_argument_type second_argument_type; }; template struct reference_wrapper_base_impl : public sprout::weak_result_type { public: typedef typename T::argument_type argument_type; typedef typename T::first_argument_type first_argument_type; typedef typename T::second_argument_type second_argument_type; }; template struct reference_wrapper_base : public sprout::detail::reference_wrapper_base_impl< sprout::has_argument_type::value, sprout::has_first_argument_type::value && sprout::has_second_argument_type::value , T > {}; template struct reference_wrapper_base : public sprout::unary_function {}; template struct reference_wrapper_base : public sprout::unary_function {}; template struct reference_wrapper_base : public sprout::unary_function {}; template struct reference_wrapper_base : public sprout::unary_function {}; template struct reference_wrapper_base : public sprout::binary_function {}; template struct reference_wrapper_base : public sprout::binary_function {}; template struct reference_wrapper_base : public sprout::binary_function {}; template struct reference_wrapper_base : public sprout::binary_function {}; template struct reference_wrapper_base : public sprout::unary_function {}; template struct reference_wrapper_base : public sprout::binary_function {}; template struct reference_wrapper_base : public sprout::unary_function {}; template struct reference_wrapper_base : public sprout::binary_function {}; template struct reference_wrapper_base : public sprout::unary_function {}; template struct reference_wrapper_base : public sprout::binary_function {}; template struct reference_wrapper_base : public sprout::unary_function {}; template struct reference_wrapper_base : public sprout::binary_function {}; template struct reference_wrapper_base : public sprout::unary_function {}; template struct reference_wrapper_base : public sprout::binary_function {}; } // namespace detail template class reference_wrapper : public sprout::detail::reference_wrapper_base::type> { public: // types typedef T type; private: T* t_; private: reference_wrapper(T&&) SPROUT_DELETED_FUNCTION_DECL public: // construct/copy/destroy SPROUT_CONSTEXPR reference_wrapper(T& t) SPROUT_NOEXCEPT : t_(&t) {} reference_wrapper(reference_wrapper const&) = default; // assignment SPROUT_CXX14_CONSTEXPR reference_wrapper& operator=(reference_wrapper const& rhs) { t_ = rhs.t_; return *this; } // access SPROUT_CONSTEXPR operator T& () const SPROUT_NOEXCEPT { return *t_; } SPROUT_CONSTEXPR T& get() const SPROUT_NOEXCEPT { return *t_; } SPROUT_CONSTEXPR T* get_pointer() const SPROUT_NOEXCEPT { return t_; } // invocation template SPROUT_CONSTEXPR typename std::result_of::type operator()(Args&&... args) const { return (*t_)(sprout::forward(args)...); } }; // // ref // cref // template inline SPROUT_CONSTEXPR sprout::reference_wrapper ref(T& t) SPROUT_NOEXCEPT { return sprout::reference_wrapper(t); } template inline SPROUT_CONSTEXPR sprout::reference_wrapper cref(T const& t) SPROUT_NOEXCEPT { return sprout::reference_wrapper(t); } template void ref(T const&&) SPROUT_DELETED_FUNCTION_DECL template void cref(T const&&) SPROUT_DELETED_FUNCTION_DECL template inline SPROUT_CONSTEXPR sprout::reference_wrapper ref(sprout::reference_wrapper t) SPROUT_NOEXCEPT { return t; } template inline SPROUT_CONSTEXPR sprout::reference_wrapper cref(sprout::reference_wrapper t) SPROUT_NOEXCEPT { return sprout::reference_wrapper(t.get()); } // // is_reference_wrapper // template struct is_reference_wrapper : public std::false_type {}; template struct is_reference_wrapper : public sprout::is_reference_wrapper {}; template struct is_reference_wrapper : public sprout::is_reference_wrapper {}; template struct is_reference_wrapper : public sprout::is_reference_wrapper {}; template struct is_reference_wrapper > : public std::true_type {}; // // unwrap_reference // template struct unwrap_reference { public: typedef T type; }; template struct unwrap_reference > { public: typedef T type; }; template struct unwrap_reference > { public: typedef T type; }; template struct unwrap_reference : public sprout::unwrap_reference {}; template struct unwrap_reference : public sprout::unwrap_reference {}; template struct unwrap_reference : public sprout::unwrap_reference {}; // // strip_reference // template struct strip_reference { public: typedef T type; }; template struct strip_reference > { public: typedef T& type; }; template struct strip_reference > { public: typedef T& type; }; template struct strip_reference : public sprout::strip_reference {}; template struct strip_reference : public sprout::strip_reference {}; template struct strip_reference : public sprout::strip_reference {}; // // unwrap_ref // template inline SPROUT_CONSTEXPR typename sprout::unwrap_reference::type& unwrap_ref(T& t) { return t; } template inline SPROUT_CONSTEXPR typename sprout::unwrap_reference::type& unwrap_ref(T const& t) { return t; } // // get_pointer // template inline SPROUT_CONSTEXPR T* get_pointer(sprout::reference_wrapper const& r) { return r.get_pointer(); } template inline SPROUT_CONSTEXPR T* get_pointer(std::reference_wrapper const& r) { return &r.get(); } } // namespace sprout #endif // #ifndef SPROUT_FUNCTIONAL_REF_HPP