| [29] | 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 | |
|---|