1 // Copyright David Abrahams 2001.
2 // Distributed under the Boost Software License, Version 1.0. (See
3 // accompanying file LICENSE_1_0.txt or copy at
4 // http://www.boost.org/LICENSE_1_0.txt)
5 #ifndef FORWARD_DWA20011215_HPP
6 # define FORWARD_DWA20011215_HPP
7 
8 # include <boost/mpl/if.hpp>
9 # include <boost/ref.hpp>
10 # include <boost/python/detail/value_arg.hpp>
11 # include <boost/python/detail/type_traits.hpp>
12 # include <boost/python/detail/copy_ctor_mutates_rhs.hpp>
13 # include <boost/mpl/or.hpp>
14 
15 namespace boost { namespace python { namespace objects {
16 
17 // Very much like boost::reference_wrapper<T>, except that in this
18 // case T can be a reference already without causing a
19 // reference-to-reference error.
20 template <class T>
21 struct reference_to_value
22 {
23     typedef typename boost::python::detail::add_lvalue_reference<typename
24         boost::python::detail::add_const<T>::type>::type reference;
25 
reference_to_valueboost::python::objects::reference_to_value26     reference_to_value(reference x) : m_value(x) {}
getboost::python::objects::reference_to_value27     reference get() const { return m_value; }
28  private:
29     reference m_value;
30 };
31 
32 // A little metaprogram which selects the type to pass through an
33 // intermediate forwarding function when the destination argument type
34 // is T.
35 template <class T>
36 struct forward
37     : mpl::if_<
38           mpl::or_<python::detail::copy_ctor_mutates_rhs<T>, boost::python::detail::is_scalar<T> >
39         , T
40         , reference_to_value<T>
41       >
42 {
43 };
44 
45 template<typename T>
46 struct unforward
47 {
48     typedef typename unwrap_reference<T>::type& type;
49 };
50 
51 template<typename T>
52 struct unforward<reference_to_value<T> >
53 {
54     typedef T type;
55 };
56 
57 template <typename T>
58 struct unforward_cref
59   : python::detail::value_arg<
60         typename unwrap_reference<T>::type
61     >
62 {
63 };
64 
65 template<typename T>
66 struct unforward_cref<reference_to_value<T> >
67   : boost::python::detail::add_lvalue_reference<typename boost::python::detail::add_const<T>::type>
68 {
69 };
70 
71 
72 template <class T>
73 typename reference_to_value<T>::reference
do_unforward(reference_to_value<T> const & x,int)74 do_unforward(reference_to_value<T> const& x, int)
75 {
76     return x.get();
77 }
78 
79 template <class T>
80 typename reference_wrapper<T>::type&
do_unforward(reference_wrapper<T> const & x,int)81 do_unforward(reference_wrapper<T> const& x, int)
82 {
83     return x.get();
84 }
85 
86 template <class T>
do_unforward(T const & x,...)87 T const& do_unforward(T const& x, ...)
88 {
89     return x;
90 }
91 
92 }}} // namespace boost::python::objects
93 
94 #endif // FORWARD_DWA20011215_HPP
95