summaryrefslogtreecommitdiff
path: root/boost/python/detail/def_helper.hpp
blob: 24f9c5cdb21c35905b1e22ef53d02b24134cc1d4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
// Copyright David Abrahams 2002.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef DEF_HELPER_DWA200287_HPP
# define DEF_HELPER_DWA200287_HPP

# include <boost/python/args.hpp>
# include <boost/python/detail/indirect_traits.hpp>
# include <boost/python/detail/type_traits.hpp>
# include <boost/mpl/not.hpp>
# include <boost/mpl/and.hpp>
# include <boost/mpl/or.hpp>
# include <boost/mpl/lambda.hpp>
# include <boost/mpl/apply.hpp>
# include <boost/tuple/tuple.hpp>
# include <boost/python/detail/not_specified.hpp>
# include <boost/python/detail/def_helper_fwd.hpp>

namespace boost { namespace python {

struct default_call_policies;

namespace detail
{
  // tuple_extract<Tuple,Predicate>::extract(t) returns the first
  // element of a Tuple whose type E satisfies the given Predicate
  // applied to add_reference<E>. The Predicate must be an MPL
  // metafunction class.
  template <class Tuple, class Predicate>
  struct tuple_extract;

  // Implementation class for when the tuple's head type does not
  // satisfy the Predicate
  template <bool matched>
  struct tuple_extract_impl
  {
      template <class Tuple, class Predicate>
      struct apply
      {
          typedef typename Tuple::head_type result_type;
          
          static typename Tuple::head_type extract(Tuple const& x)
          {
              return x.get_head();
          }
      };
  };

  // Implementation specialization for when the tuple's head type
  // satisfies the predicate
  template <>
  struct tuple_extract_impl<false>
  {
      template <class Tuple, class Predicate>
      struct apply
      {
          // recursive application of tuple_extract on the tail of the tuple
          typedef tuple_extract<typename Tuple::tail_type, Predicate> next;
          typedef typename next::result_type result_type;
          
          static result_type extract(Tuple const& x)
          {
              return next::extract(x.get_tail());
          }
      };
  };

  // A metafunction which selects a version of tuple_extract_impl to
  // use for the implementation of tuple_extract
  template <class Tuple, class Predicate>
  struct tuple_extract_base_select
  {
      typedef typename Tuple::head_type head_type;
      typedef typename mpl::apply1<Predicate,
              typename add_lvalue_reference<head_type>::type>::type match_t;
      BOOST_STATIC_CONSTANT(bool, match = match_t::value);
      typedef typename tuple_extract_impl<match>::template apply<Tuple,Predicate> type;
  };
  
  template <class Tuple, class Predicate>
  struct tuple_extract
      : tuple_extract_base_select<
         Tuple
         , typename mpl::lambda<Predicate>::type
      >::type
  {
  };


  //
  // Specialized extractors for the docstring, keywords, CallPolicies,
  // and default implementation of virtual functions
  //

  template <class Tuple>
  struct doc_extract
      : tuple_extract<
        Tuple
        , mpl::not_<
           mpl::or_<
               indirect_traits::is_reference_to_class<mpl::_1>
             , indirect_traits::is_reference_to_member_function_pointer<mpl::_1 >
           >
        >
     >
  {
  };
  
  template <class Tuple>
  struct keyword_extract
      : tuple_extract<Tuple, is_reference_to_keywords<mpl::_1 > >
  {
  };

  template <class Tuple>
  struct policy_extract
      : tuple_extract<
          Tuple
          , mpl::and_<
             mpl::not_<is_same<not_specified const&,mpl::_1> >
              , indirect_traits::is_reference_to_class<mpl::_1 >
              , mpl::not_<is_reference_to_keywords<mpl::_1 > >
          >
        >
  {
  };

  template <class Tuple>
  struct default_implementation_extract
      : tuple_extract<
          Tuple
          , indirect_traits::is_reference_to_member_function_pointer<mpl::_1 >
          >
  {
  };

  //
  // A helper class for decoding the optional arguments to def()
  // invocations, which can be supplied in any order and are
  // discriminated by their type properties. The template parameters
  // are expected to be the types of the actual (optional) arguments
  // passed to def().
  //
  template <class T1, class T2, class T3, class T4>
  struct def_helper
  {
      // A tuple type which begins with references to the supplied
      // arguments and ends with actual representatives of the default
      // types.
      typedef boost::tuples::tuple<
          T1 const&
          , T2 const&
          , T3 const&
          , T4 const&
          , default_call_policies
          , detail::keywords<0>
          , char const*
          , void(not_specified::*)()   // A function pointer type which is never an
                                       // appropriate default implementation
          > all_t;

      // Constructors; these initialize an member of the tuple type
      // shown above.
      def_helper(T1 const& a1) : m_all(a1,m_nil,m_nil,m_nil) {}
      def_helper(T1 const& a1, T2 const& a2) : m_all(a1,a2,m_nil,m_nil) {}
      def_helper(T1 const& a1, T2 const& a2, T3 const& a3) : m_all(a1,a2,a3,m_nil) {}
      def_helper(T1 const& a1, T2 const& a2, T3 const& a3, T4 const& a4) : m_all(a1,a2,a3,a4) {}

   private: // types
      typedef typename default_implementation_extract<all_t>::result_type default_implementation_t;
      
   public: // Constants which can be used for static assertions.

      // Users must not supply a default implementation for non-class
      // methods.
      BOOST_STATIC_CONSTANT(
          bool, has_default_implementation = (
              !is_same<default_implementation_t, void(not_specified::*)()>::value));
      
   public: // Extractor functions which pull the appropriate value out
           // of the tuple
      char const* doc() const
      {
          return doc_extract<all_t>::extract(m_all);
      }
      
      typename keyword_extract<all_t>::result_type keywords() const
      {
          return keyword_extract<all_t>::extract(m_all);
      }
      
      typename policy_extract<all_t>::result_type policies() const
      {
          return policy_extract<all_t>::extract(m_all);
      }

      default_implementation_t default_implementation() const
      {
          return default_implementation_extract<all_t>::extract(m_all);
      }
      
   private: // data members
      all_t m_all; 
      not_specified m_nil; // for filling in not_specified slots
  };
}

}} // namespace boost::python::detail

#endif // DEF_HELPER_DWA200287_HPP