Chris@16: // Copyright David Abrahams 2001. Chris@16: // Distributed under the Boost Software License, Version 1.0. (See Chris@16: // accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: #ifndef FORWARD_DWA20011215_HPP Chris@16: # define FORWARD_DWA20011215_HPP Chris@16: Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # if BOOST_WORKAROUND(BOOST_MSVC, < 1300) Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # else Chris@16: # include Chris@16: # endif Chris@16: Chris@16: namespace boost { namespace python { namespace objects { Chris@16: Chris@16: // Very much like boost::reference_wrapper, except that in this Chris@16: // case T can be a reference already without causing a Chris@16: // reference-to-reference error. Chris@16: template Chris@16: struct reference_to_value Chris@16: { Chris@16: typedef typename add_reference::type>::type reference; Chris@16: Chris@16: reference_to_value(reference x) : m_value(x) {} Chris@16: reference get() const { return m_value; } Chris@16: private: Chris@16: reference m_value; Chris@16: }; Chris@16: Chris@16: // A little metaprogram which selects the type to pass through an Chris@16: // intermediate forwarding function when the destination argument type Chris@16: // is T. Chris@16: template Chris@16: struct forward Chris@16: : mpl::if_< Chris@16: # if BOOST_WORKAROUND(BOOST_MSVC, < 1300) Chris@16: // vc6 chokes on unforwarding enums nested in classes Chris@16: mpl::and_< Chris@16: is_scalar Chris@16: , mpl::not_< Chris@16: is_enum Chris@16: > Chris@16: > Chris@16: # else Chris@16: mpl::or_, is_scalar > Chris@16: # endif Chris@16: , T Chris@16: , reference_to_value Chris@16: > Chris@16: { Chris@16: }; Chris@16: Chris@16: # ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION Chris@16: template Chris@16: struct unforward Chris@16: { Chris@16: typedef typename unwrap_reference::type& type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct unforward > Chris@16: { Chris@16: typedef T type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct unforward_cref Chris@16: : python::detail::value_arg< Chris@16: typename unwrap_reference::type Chris@16: > Chris@16: { Chris@16: }; Chris@16: Chris@16: template Chris@16: struct unforward_cref > Chris@16: : add_reference::type> Chris@16: { Chris@16: }; Chris@16: Chris@16: # else // no partial specialization Chris@16: Chris@16: namespace detail Chris@16: { Chris@16: typedef char (&yes_reference_to_value_t)[1]; Chris@16: typedef char (&no_reference_to_value_t)[2]; Chris@16: Chris@16: no_reference_to_value_t is_reference_to_value_test(...); Chris@16: Chris@16: template Chris@16: yes_reference_to_value_t is_reference_to_value_test(boost::type< reference_to_value >); Chris@16: Chris@16: template Chris@16: struct unforwarder Chris@16: { Chris@16: template Chris@16: struct apply Chris@16: { Chris@16: typedef typename unwrap_reference::type& type; Chris@16: }; Chris@16: }; Chris@16: Chris@16: template<> Chris@16: struct unforwarder Chris@16: { Chris@16: template Chris@16: struct apply Chris@16: { Chris@16: typedef typename T::reference type; Chris@16: }; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct cref_unforwarder Chris@16: { Chris@16: template Chris@16: struct apply Chris@16: : python::detail::value_arg< Chris@16: typename unwrap_reference::type Chris@16: > Chris@16: { Chris@16: }; Chris@16: }; Chris@16: Chris@16: template<> Chris@16: struct cref_unforwarder Chris@16: { Chris@16: template Chris@16: struct apply Chris@16: : python::detail::value_arg< Chris@16: typename T::reference Chris@16: > Chris@16: { Chris@16: }; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct is_reference_to_value Chris@16: { Chris@16: BOOST_STATIC_CONSTANT( Chris@16: bool, value = ( Chris@16: sizeof(is_reference_to_value_test(boost::type())) Chris@16: == sizeof(yes_reference_to_value_t))); Chris@16: typedef mpl::bool_ type; Chris@16: }; Chris@16: } Chris@16: Chris@16: template Chris@16: struct unforward Chris@16: : public detail::unforwarder< Chris@16: detail::is_reference_to_value::value Chris@16: >::template apply Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct unforward_cref Chris@16: : public detail::cref_unforwarder< Chris@16: detail::is_reference_to_value::value Chris@16: >::template apply Chris@16: {}; Chris@16: Chris@16: # endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION Chris@16: Chris@16: template Chris@16: typename reference_to_value::reference Chris@16: do_unforward(reference_to_value const& x, int) Chris@16: { Chris@16: return x.get(); Chris@16: } Chris@16: Chris@16: template Chris@16: typename reference_wrapper::type& Chris@16: do_unforward(reference_wrapper const& x, int) Chris@16: { Chris@16: return x.get(); Chris@16: } Chris@16: Chris@16: template Chris@16: T const& do_unforward(T const& x, ...) Chris@16: { Chris@16: return x; Chris@16: } Chris@16: Chris@16: }}} // namespace boost::python::objects Chris@16: Chris@16: #endif // FORWARD_DWA20011215_HPP