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