[12] | 1 | /////////////////////////////////////////////////////////////////////////////// |
---|
| 2 | // |
---|
| 3 | // Copyright David Abrahams 2002, Joel de Guzman, 2002. |
---|
| 4 | // Distributed under the Boost Software License, Version 1.0. (See |
---|
| 5 | // accompanying file LICENSE_1_0.txt or copy at |
---|
| 6 | // http://www.boost.org/LICENSE_1_0.txt) |
---|
| 7 | // |
---|
| 8 | /////////////////////////////////////////////////////////////////////////////// |
---|
| 9 | #ifndef INIT_JDG20020820_HPP |
---|
| 10 | #define INIT_JDG20020820_HPP |
---|
| 11 | |
---|
| 12 | # include <boost/python/detail/prefix.hpp> |
---|
| 13 | |
---|
| 14 | #include <boost/python/detail/type_list.hpp> |
---|
| 15 | #include <boost/python/args_fwd.hpp> |
---|
| 16 | #include <boost/python/detail/make_keyword_range_fn.hpp> |
---|
| 17 | #include <boost/python/def_visitor.hpp> |
---|
| 18 | |
---|
| 19 | #include <boost/mpl/if.hpp> |
---|
| 20 | #include <boost/mpl/eval_if.hpp> |
---|
| 21 | #include <boost/mpl/size.hpp> |
---|
| 22 | #include <boost/mpl/iterator_range.hpp> |
---|
| 23 | #include <boost/mpl/empty.hpp> |
---|
| 24 | #include <boost/mpl/begin_end.hpp> |
---|
| 25 | #include <boost/mpl/bool.hpp> |
---|
| 26 | #include <boost/mpl/prior.hpp> |
---|
| 27 | #include <boost/mpl/joint_view.hpp> |
---|
| 28 | #include <boost/mpl/back.hpp> |
---|
| 29 | |
---|
| 30 | #include <boost/type_traits/is_same.hpp> |
---|
| 31 | |
---|
| 32 | #include <boost/preprocessor/enum_params_with_a_default.hpp> |
---|
| 33 | #include <boost/preprocessor/enum_params.hpp> |
---|
| 34 | |
---|
| 35 | #include <utility> |
---|
| 36 | |
---|
| 37 | /////////////////////////////////////////////////////////////////////////////// |
---|
| 38 | #define BOOST_PYTHON_OVERLOAD_TYPES_WITH_DEFAULT \ |
---|
| 39 | BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( \ |
---|
| 40 | BOOST_PYTHON_MAX_ARITY, \ |
---|
| 41 | class T, \ |
---|
| 42 | mpl::void_) \ |
---|
| 43 | |
---|
| 44 | #define BOOST_PYTHON_OVERLOAD_TYPES \ |
---|
| 45 | BOOST_PP_ENUM_PARAMS_Z(1, \ |
---|
| 46 | BOOST_PYTHON_MAX_ARITY, \ |
---|
| 47 | class T) \ |
---|
| 48 | |
---|
| 49 | #define BOOST_PYTHON_OVERLOAD_ARGS \ |
---|
| 50 | BOOST_PP_ENUM_PARAMS_Z(1, \ |
---|
| 51 | BOOST_PYTHON_MAX_ARITY, \ |
---|
| 52 | T) \ |
---|
| 53 | |
---|
| 54 | /////////////////////////////////////////////////////////////////////////////// |
---|
| 55 | namespace boost { namespace python { |
---|
| 56 | |
---|
| 57 | template <BOOST_PYTHON_OVERLOAD_TYPES_WITH_DEFAULT> |
---|
| 58 | class init; // forward declaration |
---|
| 59 | |
---|
| 60 | |
---|
| 61 | template <BOOST_PYTHON_OVERLOAD_TYPES_WITH_DEFAULT> |
---|
| 62 | struct optional; // forward declaration |
---|
| 63 | |
---|
| 64 | namespace detail |
---|
| 65 | { |
---|
| 66 | namespace error |
---|
| 67 | { |
---|
| 68 | template <int keywords, int init_args> |
---|
| 69 | struct more_keywords_than_init_arguments |
---|
| 70 | { |
---|
| 71 | typedef char too_many_keywords[init_args - keywords >= 0 ? 1 : -1]; |
---|
| 72 | }; |
---|
| 73 | } |
---|
| 74 | |
---|
| 75 | // is_optional<T>::value |
---|
| 76 | // |
---|
| 77 | // This metaprogram checks if T is an optional |
---|
| 78 | // |
---|
| 79 | #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) |
---|
| 80 | |
---|
| 81 | template <class T> |
---|
| 82 | struct is_optional { |
---|
| 83 | |
---|
| 84 | private: |
---|
| 85 | |
---|
| 86 | template <BOOST_PYTHON_OVERLOAD_TYPES> |
---|
| 87 | static boost::type_traits::yes_type f(optional<BOOST_PYTHON_OVERLOAD_ARGS>); |
---|
| 88 | static boost::type_traits::no_type f(...); |
---|
| 89 | static T t(); |
---|
| 90 | |
---|
| 91 | public: |
---|
| 92 | |
---|
| 93 | BOOST_STATIC_CONSTANT( |
---|
| 94 | bool, value = |
---|
| 95 | sizeof(f(t())) == sizeof(::boost::type_traits::yes_type)); |
---|
| 96 | typedef mpl::bool_<value> type; |
---|
| 97 | }; |
---|
| 98 | |
---|
| 99 | #else |
---|
| 100 | |
---|
| 101 | template <class T> |
---|
| 102 | struct is_optional |
---|
| 103 | : mpl::false_ |
---|
| 104 | {}; |
---|
| 105 | |
---|
| 106 | template <BOOST_PYTHON_OVERLOAD_TYPES> |
---|
| 107 | struct is_optional<optional<BOOST_PYTHON_OVERLOAD_ARGS> > |
---|
| 108 | : mpl::true_ |
---|
| 109 | {}; |
---|
| 110 | |
---|
| 111 | #endif |
---|
| 112 | |
---|
| 113 | template <int NDefaults> |
---|
| 114 | struct define_class_init_helper; |
---|
| 115 | |
---|
| 116 | } // namespace detail |
---|
| 117 | |
---|
| 118 | template <class DerivedT> |
---|
| 119 | struct init_base : def_visitor<DerivedT> |
---|
| 120 | { |
---|
| 121 | init_base(char const* doc_, detail::keyword_range const& keywords_) |
---|
| 122 | : m_doc(doc_), m_keywords(keywords_) |
---|
| 123 | {} |
---|
| 124 | |
---|
| 125 | init_base(char const* doc_) |
---|
| 126 | : m_doc(doc_) |
---|
| 127 | {} |
---|
| 128 | |
---|
| 129 | DerivedT const& derived() const |
---|
| 130 | { |
---|
| 131 | return *static_cast<DerivedT const*>(this); |
---|
| 132 | } |
---|
| 133 | |
---|
| 134 | char const* doc_string() const |
---|
| 135 | { |
---|
| 136 | return m_doc; |
---|
| 137 | } |
---|
| 138 | |
---|
| 139 | detail::keyword_range const& keywords() const |
---|
| 140 | { |
---|
| 141 | return m_keywords; |
---|
| 142 | } |
---|
| 143 | |
---|
| 144 | static default_call_policies call_policies() |
---|
| 145 | { |
---|
| 146 | return default_call_policies(); |
---|
| 147 | } |
---|
| 148 | |
---|
| 149 | private: |
---|
| 150 | // visit |
---|
| 151 | // |
---|
| 152 | // Defines a set of n_defaults + 1 constructors for its |
---|
| 153 | // class_<...> argument. Each constructor after the first has |
---|
| 154 | // one less argument to its right. Example: |
---|
| 155 | // |
---|
| 156 | // init<int, optional<char, long, double> > |
---|
| 157 | // |
---|
| 158 | // Defines: |
---|
| 159 | // |
---|
| 160 | // __init__(int, char, long, double) |
---|
| 161 | // __init__(int, char, long) |
---|
| 162 | // __init__(int, char) |
---|
| 163 | // __init__(int) |
---|
| 164 | template <class classT> |
---|
| 165 | void visit(classT& cl) const |
---|
| 166 | { |
---|
| 167 | typedef typename DerivedT::signature signature; |
---|
| 168 | typedef typename DerivedT::n_arguments n_arguments; |
---|
| 169 | typedef typename DerivedT::n_defaults n_defaults; |
---|
| 170 | |
---|
| 171 | detail::define_class_init_helper<n_defaults::value>::apply( |
---|
| 172 | cl |
---|
| 173 | , derived().call_policies() |
---|
| 174 | , signature() |
---|
| 175 | , n_arguments() |
---|
| 176 | , derived().doc_string() |
---|
| 177 | , derived().keywords()); |
---|
| 178 | } |
---|
| 179 | |
---|
| 180 | friend class python::def_visitor_access; |
---|
| 181 | |
---|
| 182 | private: // data members |
---|
| 183 | char const* m_doc; |
---|
| 184 | detail::keyword_range m_keywords; |
---|
| 185 | }; |
---|
| 186 | |
---|
| 187 | template <class CallPoliciesT, class InitT> |
---|
| 188 | class init_with_call_policies |
---|
| 189 | : public init_base<init_with_call_policies<CallPoliciesT, InitT> > |
---|
| 190 | { |
---|
| 191 | typedef init_base<init_with_call_policies<CallPoliciesT, InitT> > base; |
---|
| 192 | public: |
---|
| 193 | typedef typename InitT::n_arguments n_arguments; |
---|
| 194 | typedef typename InitT::n_defaults n_defaults; |
---|
| 195 | typedef typename InitT::signature signature; |
---|
| 196 | |
---|
| 197 | init_with_call_policies( |
---|
| 198 | CallPoliciesT const& policies_ |
---|
| 199 | , char const* doc_ |
---|
| 200 | , detail::keyword_range const& keywords |
---|
| 201 | ) |
---|
| 202 | : base(doc_, keywords) |
---|
| 203 | , m_policies(policies_) |
---|
| 204 | {} |
---|
| 205 | |
---|
| 206 | CallPoliciesT const& call_policies() const |
---|
| 207 | { |
---|
| 208 | return this->m_policies; |
---|
| 209 | } |
---|
| 210 | |
---|
| 211 | private: // data members |
---|
| 212 | CallPoliciesT m_policies; |
---|
| 213 | }; |
---|
| 214 | |
---|
| 215 | // |
---|
| 216 | // drop1<S> is the initial length(S) elements of S |
---|
| 217 | // |
---|
| 218 | namespace detail |
---|
| 219 | { |
---|
| 220 | template <class S> |
---|
| 221 | struct drop1 |
---|
| 222 | : mpl::iterator_range< |
---|
| 223 | typename mpl::begin<S>::type |
---|
| 224 | , typename mpl::prior< |
---|
| 225 | typename mpl::end<S>::type |
---|
| 226 | >::type |
---|
| 227 | > |
---|
| 228 | {}; |
---|
| 229 | } |
---|
| 230 | |
---|
| 231 | template <BOOST_PYTHON_OVERLOAD_TYPES> |
---|
| 232 | class init : public init_base<init<BOOST_PYTHON_OVERLOAD_ARGS> > |
---|
| 233 | { |
---|
| 234 | typedef init_base<init<BOOST_PYTHON_OVERLOAD_ARGS> > base; |
---|
| 235 | public: |
---|
| 236 | typedef init<BOOST_PYTHON_OVERLOAD_ARGS> self_t; |
---|
| 237 | |
---|
| 238 | init(char const* doc_ = 0) |
---|
| 239 | : base(doc_) |
---|
| 240 | { |
---|
| 241 | } |
---|
| 242 | |
---|
| 243 | template <std::size_t N> |
---|
| 244 | init(char const* doc_, detail::keywords<N> const& kw) |
---|
| 245 | : base(doc_, kw.range()) |
---|
| 246 | { |
---|
| 247 | typedef typename detail::error::more_keywords_than_init_arguments< |
---|
| 248 | N, n_arguments::value |
---|
| 249 | >::too_many_keywords assertion; |
---|
| 250 | } |
---|
| 251 | |
---|
| 252 | template <std::size_t N> |
---|
| 253 | init(detail::keywords<N> const& kw, char const* doc_ = 0) |
---|
| 254 | : base(doc_, kw.range()) |
---|
| 255 | { |
---|
| 256 | typedef typename detail::error::more_keywords_than_init_arguments< |
---|
| 257 | N, n_arguments::value |
---|
| 258 | >::too_many_keywords assertion; |
---|
| 259 | } |
---|
| 260 | |
---|
| 261 | template <class CallPoliciesT> |
---|
| 262 | init_with_call_policies<CallPoliciesT, self_t> |
---|
| 263 | operator[](CallPoliciesT const& policies) const |
---|
| 264 | { |
---|
| 265 | return init_with_call_policies<CallPoliciesT, self_t>( |
---|
| 266 | policies, this->doc_string(), this->keywords()); |
---|
| 267 | } |
---|
| 268 | |
---|
| 269 | typedef detail::type_list<BOOST_PYTHON_OVERLOAD_ARGS> signature_; |
---|
| 270 | |
---|
| 271 | typedef detail::is_optional< |
---|
| 272 | typename mpl::eval_if< |
---|
| 273 | mpl::empty<signature_> |
---|
| 274 | , mpl::false_ |
---|
| 275 | , mpl::back<signature_> |
---|
| 276 | >::type |
---|
| 277 | > back_is_optional; |
---|
| 278 | |
---|
| 279 | typedef typename mpl::eval_if< |
---|
| 280 | back_is_optional |
---|
| 281 | , mpl::back<signature_> |
---|
| 282 | , mpl::vector0<> |
---|
| 283 | >::type optional_args; |
---|
| 284 | |
---|
| 285 | typedef typename mpl::eval_if< |
---|
| 286 | back_is_optional |
---|
| 287 | , mpl::if_< |
---|
| 288 | mpl::empty<optional_args> |
---|
| 289 | , detail::drop1<signature_> |
---|
| 290 | , mpl::joint_view< |
---|
| 291 | detail::drop1<signature_> |
---|
| 292 | , optional_args |
---|
| 293 | > |
---|
| 294 | > |
---|
| 295 | , signature_ |
---|
| 296 | >::type signature; |
---|
| 297 | |
---|
| 298 | // TODO: static assert to make sure there are no other optional elements |
---|
| 299 | |
---|
| 300 | // Count the number of default args |
---|
| 301 | typedef mpl::size<optional_args> n_defaults; |
---|
| 302 | typedef mpl::size<signature> n_arguments; |
---|
| 303 | }; |
---|
| 304 | |
---|
| 305 | /////////////////////////////////////////////////////////////////////////////// |
---|
| 306 | // |
---|
| 307 | // optional |
---|
| 308 | // |
---|
| 309 | // optional<T0...TN>::type returns a typelist. |
---|
| 310 | // |
---|
| 311 | /////////////////////////////////////////////////////////////////////////////// |
---|
| 312 | template <BOOST_PYTHON_OVERLOAD_TYPES> |
---|
| 313 | struct optional |
---|
| 314 | : detail::type_list<BOOST_PYTHON_OVERLOAD_ARGS> |
---|
| 315 | { |
---|
| 316 | }; |
---|
| 317 | |
---|
| 318 | namespace detail |
---|
| 319 | { |
---|
| 320 | template <class ClassT, class CallPoliciesT, class Signature, class NArgs> |
---|
| 321 | inline void def_init_aux( |
---|
| 322 | ClassT& cl |
---|
| 323 | , Signature const& |
---|
| 324 | , NArgs |
---|
| 325 | , CallPoliciesT const& policies |
---|
| 326 | , char const* doc |
---|
| 327 | , detail::keyword_range const& keywords_ |
---|
| 328 | ) |
---|
| 329 | { |
---|
| 330 | cl.def( |
---|
| 331 | "__init__" |
---|
| 332 | , detail::make_keyword_range_constructor<Signature,NArgs>( |
---|
| 333 | policies |
---|
| 334 | , keywords_ |
---|
| 335 | , (typename ClassT::metadata::holder*)0 |
---|
| 336 | ) |
---|
| 337 | , doc |
---|
| 338 | ); |
---|
| 339 | } |
---|
| 340 | |
---|
| 341 | /////////////////////////////////////////////////////////////////////////////// |
---|
| 342 | // |
---|
| 343 | // define_class_init_helper<N>::apply |
---|
| 344 | // |
---|
| 345 | // General case |
---|
| 346 | // |
---|
| 347 | // Accepts a class_ and an arguments list. Defines a constructor |
---|
| 348 | // for the class given the arguments and recursively calls |
---|
| 349 | // define_class_init_helper<N-1>::apply with one fewer argument (the |
---|
| 350 | // rightmost argument is shaved off) |
---|
| 351 | // |
---|
| 352 | /////////////////////////////////////////////////////////////////////////////// |
---|
| 353 | template <int NDefaults> |
---|
| 354 | struct define_class_init_helper |
---|
| 355 | { |
---|
| 356 | |
---|
| 357 | template <class ClassT, class CallPoliciesT, class Signature, class NArgs> |
---|
| 358 | static void apply( |
---|
| 359 | ClassT& cl |
---|
| 360 | , CallPoliciesT const& policies |
---|
| 361 | , Signature const& args |
---|
| 362 | , NArgs |
---|
| 363 | , char const* doc |
---|
| 364 | , detail::keyword_range keywords) |
---|
| 365 | { |
---|
| 366 | detail::def_init_aux(cl, args, NArgs(), policies, 0, keywords); |
---|
| 367 | |
---|
| 368 | if (keywords.second > keywords.first) |
---|
| 369 | --keywords.second; |
---|
| 370 | |
---|
| 371 | typedef typename mpl::prior<NArgs>::type next_nargs; |
---|
| 372 | define_class_init_helper<NDefaults-1>::apply( |
---|
| 373 | cl, policies, Signature(), next_nargs(), doc, keywords); |
---|
| 374 | } |
---|
| 375 | }; |
---|
| 376 | |
---|
| 377 | /////////////////////////////////////////////////////////////////////////////// |
---|
| 378 | // |
---|
| 379 | // define_class_init_helper<0>::apply |
---|
| 380 | // |
---|
| 381 | // Terminal case |
---|
| 382 | // |
---|
| 383 | // Accepts a class_ and an arguments list. Defines a constructor |
---|
| 384 | // for the class given the arguments. |
---|
| 385 | // |
---|
| 386 | /////////////////////////////////////////////////////////////////////////////// |
---|
| 387 | template <> |
---|
| 388 | struct define_class_init_helper<0> { |
---|
| 389 | |
---|
| 390 | template <class ClassT, class CallPoliciesT, class Signature, class NArgs> |
---|
| 391 | static void apply( |
---|
| 392 | ClassT& cl |
---|
| 393 | , CallPoliciesT const& policies |
---|
| 394 | , Signature const& args |
---|
| 395 | , NArgs |
---|
| 396 | , char const* doc |
---|
| 397 | , detail::keyword_range const& keywords) |
---|
| 398 | { |
---|
| 399 | detail::def_init_aux(cl, args, NArgs(), policies, doc, keywords); |
---|
| 400 | } |
---|
| 401 | }; |
---|
| 402 | } |
---|
| 403 | |
---|
| 404 | }} // namespace boost::python |
---|
| 405 | |
---|
| 406 | #undef BOOST_PYTHON_OVERLOAD_TYPES_WITH_DEFAULT |
---|
| 407 | #undef BOOST_PYTHON_OVERLOAD_TYPES |
---|
| 408 | #undef BOOST_PYTHON_OVERLOAD_ARGS |
---|
| 409 | #undef BOOST_PYTHON_IS_OPTIONAL_VALUE |
---|
| 410 | #undef BOOST_PYTHON_APPEND_TO_INIT |
---|
| 411 | |
---|
| 412 | /////////////////////////////////////////////////////////////////////////////// |
---|
| 413 | #endif // INIT_JDG20020820_HPP |
---|
| 414 | |
---|
| 415 | |
---|
| 416 | |
---|
| 417 | |
---|
| 418 | |
---|
| 419 | |
---|
| 420 | |
---|
| 421 | |
---|