1 // Copyright David Abrahams 2002.
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 DEF_HELPER_DWA200287_HPP
6 # define DEF_HELPER_DWA200287_HPP
7 
8 # include <boost/python/args.hpp>
9 # include <boost/type_traits/ice.hpp>
10 # include <boost/type_traits/same_traits.hpp>
11 # include <boost/python/detail/indirect_traits.hpp>
12 # include <boost/mpl/not.hpp>
13 # include <boost/mpl/and.hpp>
14 # include <boost/mpl/or.hpp>
15 # include <boost/type_traits/add_reference.hpp>
16 # include <boost/mpl/lambda.hpp>
17 # include <boost/mpl/apply.hpp>
18 # include <boost/tuple/tuple.hpp>
19 # include <boost/python/detail/not_specified.hpp>
20 # include <boost/python/detail/def_helper_fwd.hpp>
21 
22 namespace boost { namespace python {
23 
24 struct default_call_policies;
25 
26 namespace detail
27 {
28   // tuple_extract<Tuple,Predicate>::extract(t) returns the first
29   // element of a Tuple whose type E satisfies the given Predicate
30   // applied to add_reference<E>. The Predicate must be an MPL
31   // metafunction class.
32   template <class Tuple, class Predicate>
33   struct tuple_extract;
34 
35   // Implementation class for when the tuple's head type does not
36   // satisfy the Predicate
37   template <bool matched>
38   struct tuple_extract_impl
39   {
40       template <class Tuple, class Predicate>
41       struct apply
42       {
43           typedef typename Tuple::head_type result_type;
44 
extractboost::python::detail::tuple_extract_impl::apply45           static typename Tuple::head_type extract(Tuple const& x)
46           {
47               return x.get_head();
48           }
49       };
50   };
51 
52   // Implementation specialization for when the tuple's head type
53   // satisfies the predicate
54   template <>
55   struct tuple_extract_impl<false>
56   {
57       template <class Tuple, class Predicate>
58       struct apply
59       {
60           // recursive application of tuple_extract on the tail of the tuple
61           typedef tuple_extract<typename Tuple::tail_type, Predicate> next;
62           typedef typename next::result_type result_type;
63 
extractboost::python::detail::tuple_extract_impl::apply64           static result_type extract(Tuple const& x)
65           {
66               return next::extract(x.get_tail());
67           }
68       };
69   };
70 
71   // A metafunction which selects a version of tuple_extract_impl to
72   // use for the implementation of tuple_extract
73   template <class Tuple, class Predicate>
74   struct tuple_extract_base_select
75   {
76       typedef typename Tuple::head_type head_type;
77       typedef typename mpl::apply1<Predicate, typename add_reference<head_type>::type>::type match_t;
78       BOOST_STATIC_CONSTANT(bool, match = match_t::value);
79       typedef typename tuple_extract_impl<match>::template apply<Tuple,Predicate> type;
80   };
81 
82   template <class Tuple, class Predicate>
83   struct tuple_extract
84       : tuple_extract_base_select<
85          Tuple
86          , typename mpl::lambda<Predicate>::type
87       >::type
88   {
89   };
90 
91 
92   //
93   // Specialized extractors for the docstring, keywords, CallPolicies,
94   // and default implementation of virtual functions
95   //
96 
97   template <class Tuple>
98   struct doc_extract
99       : tuple_extract<
100         Tuple
101         , mpl::not_<
102            mpl::or_<
103                indirect_traits::is_reference_to_class<mpl::_1>
104              , indirect_traits::is_reference_to_member_function_pointer<mpl::_1 >
105            >
106         >
107      >
108   {
109   };
110 
111   template <class Tuple>
112   struct keyword_extract
113       : tuple_extract<Tuple, is_reference_to_keywords<mpl::_1 > >
114   {
115   };
116 
117   template <class Tuple>
118   struct policy_extract
119       : tuple_extract<
120           Tuple
121           , mpl::and_<
122              mpl::not_<is_same<not_specified const&,mpl::_1> >
123               , indirect_traits::is_reference_to_class<mpl::_1 >
124               , mpl::not_<is_reference_to_keywords<mpl::_1 > >
125           >
126         >
127   {
128   };
129 
130   template <class Tuple>
131   struct default_implementation_extract
132       : tuple_extract<
133           Tuple
134           , indirect_traits::is_reference_to_member_function_pointer<mpl::_1 >
135           >
136   {
137   };
138 
139   //
140   // A helper class for decoding the optional arguments to def()
141   // invocations, which can be supplied in any order and are
142   // discriminated by their type properties. The template parameters
143   // are expected to be the types of the actual (optional) arguments
144   // passed to def().
145   //
146   template <class T1, class T2, class T3, class T4>
147   struct def_helper
148   {
149       // A tuple type which begins with references to the supplied
150       // arguments and ends with actual representatives of the default
151       // types.
152       typedef boost::tuples::tuple<
153           T1 const&
154           , T2 const&
155           , T3 const&
156           , T4 const&
157           , default_call_policies
158           , detail::keywords<0>
159           , char const*
160           , void(not_specified::*)()   // A function pointer type which is never an
161                                        // appropriate default implementation
162           > all_t;
163 
164       // Constructors; these initialize an member of the tuple type
165       // shown above.
def_helperboost::python::detail::def_helper166       def_helper(T1 const& a1) : m_all(a1,m_nil,m_nil,m_nil) {}
def_helperboost::python::detail::def_helper167       def_helper(T1 const& a1, T2 const& a2) : m_all(a1,a2,m_nil,m_nil) {}
def_helperboost::python::detail::def_helper168       def_helper(T1 const& a1, T2 const& a2, T3 const& a3) : m_all(a1,a2,a3,m_nil) {}
def_helperboost::python::detail::def_helper169       def_helper(T1 const& a1, T2 const& a2, T3 const& a3, T4 const& a4) : m_all(a1,a2,a3,a4) {}
170 
171    private: // types
172       typedef typename default_implementation_extract<all_t>::result_type default_implementation_t;
173 
174    public: // Constants which can be used for static assertions.
175 
176       // Users must not supply a default implementation for non-class
177       // methods.
178       BOOST_STATIC_CONSTANT(
179           bool, has_default_implementation = (
180               !is_same<default_implementation_t, void(not_specified::*)()>::value));
181 
182    public: // Extractor functions which pull the appropriate value out
183            // of the tuple
docboost::python::detail::def_helper184       char const* doc() const
185       {
186           return doc_extract<all_t>::extract(m_all);
187       }
188 
keywordsboost::python::detail::def_helper189       typename keyword_extract<all_t>::result_type keywords() const
190       {
191           return keyword_extract<all_t>::extract(m_all);
192       }
193 
policiesboost::python::detail::def_helper194       typename policy_extract<all_t>::result_type policies() const
195       {
196           return policy_extract<all_t>::extract(m_all);
197       }
198 
default_implementationboost::python::detail::def_helper199       default_implementation_t default_implementation() const
200       {
201           return default_implementation_extract<all_t>::extract(m_all);
202       }
203 
204    private: // data members
205       all_t m_all;
206       not_specified m_nil; // for filling in not_specified slots
207   };
208 }
209 
210 }} // namespace boost::python::detail
211 
212 #endif // DEF_HELPER_DWA200287_HPP
213