source: NonGTP/Boost/boost/python/object/forward.hpp @ 857

Revision 857, 4.6 KB checked in by igarcia, 18 years ago (diff)
Line 
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/type_traits/is_scalar.hpp>
10# include <boost/type_traits/add_const.hpp>
11# include <boost/type_traits/add_reference.hpp>
12# include <boost/ref.hpp>
13# include <boost/python/detail/value_arg.hpp>
14# include <boost/python/detail/copy_ctor_mutates_rhs.hpp>
15# if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
16#  include <boost/type_traits/is_enum.hpp>
17#  include <boost/mpl/and.hpp>
18#  include <boost/mpl/not.hpp>
19# else
20#  include <boost/mpl/or.hpp>
21# endif
22
23namespace boost { namespace python { namespace objects {
24
25// Very much like boost::reference_wrapper<T>, except that in this
26// case T can be a reference already without causing a
27// reference-to-reference error.
28template <class T>
29struct reference_to_value
30{
31    typedef typename add_reference<typename add_const<T>::type>::type reference;
32   
33    reference_to_value(reference x) : m_value(x) {}
34    reference get() const { return m_value; }
35 private:
36    reference m_value;
37};
38
39// A little metaprogram which selects the type to pass through an
40// intermediate forwarding function when the destination argument type
41// is T.
42template <class T>
43struct forward
44    : mpl::if_<
45# if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
46          // vc6 chokes on unforwarding enums nested in classes
47          mpl::and_<
48              is_scalar<T>
49            , mpl::not_<
50                  is_enum<T>
51              >
52          >
53# else
54          mpl::or_<python::detail::copy_ctor_mutates_rhs<T>, is_scalar<T> >
55# endif
56        , T
57        , reference_to_value<T>
58      >
59{
60};
61
62# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
63template<typename T>
64struct unforward
65{
66    typedef typename unwrap_reference<T>::type& type;
67};
68
69template<typename T>
70struct unforward<reference_to_value<T> >
71{
72    typedef T type;
73};
74
75template <typename T>
76struct unforward_cref
77  : python::detail::value_arg<
78        typename unwrap_reference<T>::type
79    >
80{
81};
82
83template<typename T>
84struct unforward_cref<reference_to_value<T> >
85  : add_reference<typename add_const<T>::type>
86{
87};
88
89# else // no partial specialization
90
91namespace detail
92{
93  typedef char (&yes_reference_to_value_t)[1];
94  typedef char (&no_reference_to_value_t)[2];
95     
96  no_reference_to_value_t is_reference_to_value_test(...);
97
98  template<typename T>
99  yes_reference_to_value_t is_reference_to_value_test(boost::type< reference_to_value<T> >);
100
101  template<bool wrapped>
102  struct unforwarder
103  {
104      template <class T>
105      struct apply
106      {
107          typedef typename unwrap_reference<T>::type& type;
108      };
109  };
110
111  template<>
112  struct unforwarder<true>
113  {
114      template <class T>
115      struct apply
116      {
117          typedef typename T::reference type;
118      };
119  };
120
121  template<bool wrapped = false>
122  struct cref_unforwarder
123  {
124      template <class T>
125      struct apply
126        : python::detail::value_arg<
127              typename unwrap_reference<T>::type
128          >
129      {         
130      };
131  };
132     
133  template<>
134  struct cref_unforwarder<true>
135  {
136      template <class T>
137      struct apply
138        : python::detail::value_arg<
139              typename T::reference
140          >
141      {
142      };
143  };
144
145  template<typename T>
146  struct is_reference_to_value
147  {
148      BOOST_STATIC_CONSTANT(
149          bool, value = (
150              sizeof(is_reference_to_value_test(boost::type<T>()))
151              == sizeof(yes_reference_to_value_t)));
152      typedef mpl::bool_<value> type;
153  };
154}
155
156template <typename T>
157struct unforward
158    : public detail::unforwarder<
159        detail::is_reference_to_value<T>::value
160      >::template apply<T>
161{};
162
163template <typename T>
164struct unforward_cref
165    : public detail::cref_unforwarder<
166        detail::is_reference_to_value<T>::value
167      >::template apply<T>
168{};
169
170# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
171
172template <class T>
173typename reference_to_value<T>::reference
174do_unforward(reference_to_value<T> const& x, int)
175{
176    return x.get();
177}
178
179template <class T>
180typename reference_wrapper<T>::type&
181do_unforward(reference_wrapper<T> const& x, int)
182{
183    return x.get();
184}
185
186template <class T>
187T const& do_unforward(T const& x, ...)
188{
189    return x;
190}
191
192}}} // namespace boost::python::objects
193
194#endif // FORWARD_DWA20011215_HPP
Note: See TracBrowser for help on using the repository browser.