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