Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-18 09:03:32

0001 // Copyright David Abrahams 2002.
0002 // Distributed under the Boost Software License, Version 1.0. (See
0003 // accompanying file LICENSE_1_0.txt or copy at
0004 // http://www.boost.org/LICENSE_1_0.txt)
0005 #ifndef CLASS_DWA200216_HPP
0006 # define CLASS_DWA200216_HPP
0007 
0008 # include <boost/python/detail/prefix.hpp>
0009 
0010 # include <boost/noncopyable.hpp>
0011 
0012 # include <boost/python/class_fwd.hpp>
0013 # include <boost/python/object/class.hpp>
0014 
0015 # include <boost/python/object.hpp>
0016 # include <boost/python/type_id.hpp>
0017 # include <boost/python/data_members.hpp>
0018 # include <boost/python/make_function.hpp>
0019 # include <boost/python/signature.hpp>
0020 # include <boost/python/init.hpp>
0021 # include <boost/python/args_fwd.hpp>
0022 
0023 # include <boost/python/object/class_metadata.hpp>
0024 # include <boost/python/object/pickle_support.hpp>
0025 # include <boost/python/object/add_to_namespace.hpp>
0026 
0027 # include <boost/python/detail/overloads_fwd.hpp>
0028 # include <boost/python/detail/operator_id.hpp>
0029 # include <boost/python/detail/def_helper.hpp>
0030 # include <boost/python/detail/force_instantiate.hpp>
0031 # include <boost/python/detail/type_traits.hpp>
0032 # include <boost/python/detail/unwrap_type_id.hpp>
0033 # include <boost/python/detail/unwrap_wrapper.hpp>
0034 
0035 # include <boost/mpl/size.hpp>
0036 # include <boost/mpl/for_each.hpp>
0037 # include <boost/mpl/bool.hpp>
0038 # include <boost/mpl/not.hpp>
0039 
0040 # include <boost/detail/workaround.hpp>
0041 
0042 # if BOOST_WORKAROUND(__MWERKS__, <= 0x3004)                        \
0043     /* pro9 reintroduced the bug */                                 \
0044     || (BOOST_WORKAROUND(__MWERKS__, > 0x3100)                      \
0045         && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))
0046 
0047 #  define BOOST_PYTHON_NO_MEMBER_POINTER_ORDERING 1
0048 
0049 # endif
0050 
0051 # ifdef BOOST_PYTHON_NO_MEMBER_POINTER_ORDERING
0052 #  include <boost/mpl/and.hpp>
0053 # endif
0054 
0055 namespace boost { namespace python {
0056 
0057 template <class DerivedVisitor> class def_visitor;
0058 
0059 enum no_init_t { no_init };
0060 
0061 namespace detail
0062 {
0063   // This function object is used with mpl::for_each to write the id
0064   // of the type a pointer to which is passed as its 2nd compile-time
0065   // argument. into the iterator pointed to by its runtime argument
0066   struct write_type_id
0067   {
0068       write_type_id(type_info**p) : p(p) {}
0069 
0070       // Here's the runtime behavior
0071       template <class T>
0072       void operator()(T*) const
0073       {
0074           *(*p)++ = type_id<T>();
0075       }
0076 
0077       type_info** p;
0078   };
0079 
0080   template <class T>
0081   struct is_data_member_pointer
0082       : mpl::and_<
0083             detail::is_member_pointer<T>
0084           , mpl::not_<detail::is_member_function_pointer<T> >
0085         >
0086   {};
0087   
0088 # ifdef BOOST_PYTHON_NO_MEMBER_POINTER_ORDERING
0089 #  define BOOST_PYTHON_DATA_MEMBER_HELPER(D) , detail::is_data_member_pointer<D>()
0090 #  define BOOST_PYTHON_YES_DATA_MEMBER , mpl::true_
0091 #  define BOOST_PYTHON_NO_DATA_MEMBER , mpl::false_
0092 # elif defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
0093 #  define BOOST_PYTHON_DATA_MEMBER_HELPER(D) , 0
0094 #  define BOOST_PYTHON_YES_DATA_MEMBER , int
0095 #  define BOOST_PYTHON_NO_DATA_MEMBER , ...
0096 # else 
0097 #  define BOOST_PYTHON_DATA_MEMBER_HELPER(D)
0098 #  define BOOST_PYTHON_YES_DATA_MEMBER
0099 #  define BOOST_PYTHON_NO_DATA_MEMBER
0100 # endif
0101   
0102   namespace error
0103   {
0104     //
0105     // A meta-assertion mechanism which prints nice error messages and
0106     // backtraces on lots of compilers. Usage:
0107     //
0108     //      assertion<C>::failed
0109     //
0110     // where C is an MPL metafunction class
0111     //
0112     
0113     template <class C> struct assertion_failed { };
0114     template <class C> struct assertion_ok { typedef C failed; };
0115 
0116     template <class C>
0117     struct assertion
0118         : mpl::if_<C, assertion_ok<C>, assertion_failed<C> >::type
0119     {};
0120 
0121     //
0122     // Checks for validity of arguments used to define virtual
0123     // functions with default implementations.
0124     //
0125     
0126     template <class Default>
0127     void not_a_derived_class_member(Default) {}
0128     
0129     template <class T, class Fn>
0130     struct virtual_function_default
0131     {
0132         template <class Default>
0133         static void
0134         must_be_derived_class_member(Default const&)
0135         {
0136             // https://svn.boost.org/trac/boost/ticket/5803
0137             //typedef typename assertion<mpl::not_<detail::is_same<Default,Fn> > >::failed test0;
0138 # if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
0139             typedef typename assertion<detail::is_polymorphic<T> >::failed test1 BOOST_ATTRIBUTE_UNUSED;
0140 # endif 
0141             typedef typename assertion<detail::is_member_function_pointer<Fn> >::failed test2 BOOST_ATTRIBUTE_UNUSED;
0142             not_a_derived_class_member<Default>(Fn());
0143         }
0144     };
0145   }
0146 }
0147 
0148 // This is the primary mechanism through which users will expose
0149 // C++ classes to Python.
0150 template <
0151     class W // class being wrapped
0152     , class X1 // = detail::not_specified
0153     , class X2 // = detail::not_specified
0154     , class X3 // = detail::not_specified
0155     >
0156 class class_ : public objects::class_base
0157 {
0158  public: // types
0159     typedef objects::class_base base;
0160     typedef class_<W,X1,X2,X3> self;
0161     typedef typename objects::class_metadata<W,X1,X2,X3> metadata;
0162     typedef W wrapped_type;
0163     
0164  private: // types
0165 
0166     // A helper class which will contain an array of id objects to be
0167     // passed to the base class constructor
0168     struct id_vector
0169     {
0170         typedef typename metadata::bases bases;
0171         
0172         id_vector()
0173         {
0174             // Stick the derived class id into the first element of the array
0175             ids[0] = detail::unwrap_type_id((W*)0, (W*)0);
0176 
0177             // Write the rest of the elements into succeeding positions.
0178             type_info* p = ids + 1;
0179             mpl::for_each(detail::write_type_id(&p), (bases*)0, (add_pointer<mpl::_>*)0);
0180         }
0181 
0182         BOOST_STATIC_CONSTANT(
0183             std::size_t, size = mpl::size<bases>::value + 1);
0184         type_info ids[size];
0185     };
0186     friend struct id_vector;
0187 
0188  public: // constructors
0189     
0190     // Construct with the class name, with or without docstring, and default __init__() function
0191     class_(char const* name, char const* doc = 0);
0192 
0193     // Construct with class name, no docstring, and an uncallable __init__ function
0194     class_(char const* name, no_init_t);
0195 
0196     // Construct with class name, docstring, and an uncallable __init__ function
0197     class_(char const* name, char const* doc, no_init_t);
0198 
0199     // Construct with class name and init<> function
0200     template <class DerivedT>
0201     inline class_(char const* name, init_base<DerivedT> const& i)
0202         : base(name, id_vector::size, id_vector().ids)
0203     {
0204         this->initialize(i);
0205     }
0206 
0207     // Construct with class name, docstring and init<> function
0208     template <class DerivedT>
0209     inline class_(char const* name, char const* doc, init_base<DerivedT> const& i)
0210         : base(name, id_vector::size, id_vector().ids, doc)
0211     {
0212         this->initialize(i);
0213     }
0214 
0215  public: // member functions
0216     
0217     // Generic visitation
0218     template <class Derived>
0219     self& def(def_visitor<Derived> const& visitor)
0220     {
0221         visitor.visit(*this);
0222         return *this;
0223     }
0224 
0225     // Wrap a member function or a non-member function which can take
0226     // a T, T cv&, or T cv* as its first parameter, a callable
0227     // python object, or a generic visitor.
0228     template <class F>
0229     self& def(char const* name, F f)
0230     {
0231         this->def_impl(
0232             detail::unwrap_wrapper((W*)0)
0233           , name, f, detail::def_helper<char const*>(0), &f);
0234         return *this;
0235     }
0236 
0237     template <class A1, class A2>
0238     self& def(char const* name, A1 a1, A2 const& a2)
0239     {
0240         this->def_maybe_overloads(name, a1, a2, &a2);
0241         return *this;
0242     }
0243 
0244     template <class Fn, class A1, class A2>
0245     self& def(char const* name, Fn fn, A1 const& a1, A2 const& a2)
0246     {
0247         //  The arguments are definitely:
0248         //      def(name, function, policy, doc_string)
0249         //      def(name, function, doc_string, policy)
0250 
0251         this->def_impl(
0252             detail::unwrap_wrapper((W*)0)
0253           , name, fn
0254           , detail::def_helper<A1,A2>(a1,a2)
0255           , &fn);
0256 
0257         return *this;
0258     }
0259 
0260     template <class Fn, class A1, class A2, class A3>
0261     self& def(char const* name, Fn fn, A1 const& a1, A2 const& a2, A3 const& a3)
0262     {
0263         this->def_impl(
0264             detail::unwrap_wrapper((W*)0)
0265           , name, fn
0266           , detail::def_helper<A1,A2,A3>(a1,a2,a3)
0267           , &fn);
0268 
0269         return *this;
0270     }
0271 
0272     //
0273     // Data member access
0274     //
0275     template <class D>
0276     self& def_readonly(char const* name, D const& d, char const* doc=0)
0277     {
0278         return this->def_readonly_impl(name, d, doc BOOST_PYTHON_DATA_MEMBER_HELPER(D));
0279     }
0280 
0281     template <class D>
0282     self& def_readwrite(char const* name, D const& d, char const* doc=0)
0283     {
0284         return this->def_readwrite_impl(name, d, doc BOOST_PYTHON_DATA_MEMBER_HELPER(D));
0285     }
0286     
0287     template <class D>
0288     self& def_readonly(char const* name, D& d, char const* doc=0)
0289     {
0290         return this->def_readonly_impl(name, d, doc BOOST_PYTHON_DATA_MEMBER_HELPER(D));
0291     }
0292 
0293     template <class D>
0294     self& def_readwrite(char const* name, D& d, char const* doc=0)
0295     {
0296         return this->def_readwrite_impl(name, d, doc BOOST_PYTHON_DATA_MEMBER_HELPER(D));
0297     }
0298 
0299     // Property creation
0300     template <class Get>
0301     self& add_property(char const* name, Get fget, char const* docstr = 0)
0302     {
0303         base::add_property(name, this->make_getter(fget), docstr);
0304         return *this;
0305     }
0306 
0307     template <class Get, class Set>
0308     self& add_property(char const* name, Get fget, Set fset, char const* docstr = 0)
0309     {
0310         base::add_property(
0311             name, this->make_getter(fget), this->make_setter(fset), docstr);
0312         return *this;
0313     }
0314         
0315     template <class Get>
0316     self& add_static_property(char const* name, Get fget)
0317     {
0318         base::add_static_property(name, object(fget));
0319         return *this;
0320     }
0321 
0322     template <class Get, class Set>
0323     self& add_static_property(char const* name, Get fget, Set fset)
0324     {
0325         base::add_static_property(name, object(fget), object(fset));
0326         return *this;
0327     }
0328         
0329     template <class U>
0330     self& setattr(char const* name, U const& x)
0331     {
0332         this->base::setattr(name, object(x));
0333         return *this;
0334     }
0335 
0336     // Pickle support
0337     template <typename PickleSuiteType>
0338     self& def_pickle(PickleSuiteType const& x)
0339     {
0340       error_messages::must_be_derived_from_pickle_suite(x);
0341       detail::pickle_suite_finalize<PickleSuiteType>::register_(
0342         *this,
0343         &PickleSuiteType::getinitargs,
0344         &PickleSuiteType::getstate,
0345         &PickleSuiteType::setstate,
0346         PickleSuiteType::getstate_manages_dict());
0347       return *this;
0348     }
0349 
0350     self& enable_pickling()
0351     {
0352         this->base::enable_pickling_(false);
0353         return *this;
0354     }
0355 
0356     self& staticmethod(char const* name)
0357     {
0358         this->make_method_static(name);
0359         return *this;
0360     }
0361  private: // helper functions
0362 
0363     // Builds a method for this class around the given [member]
0364     // function pointer or object, appropriately adjusting the type of
0365     // the first signature argument so that if f is a member of a
0366     // (possibly not wrapped) base class of T, an lvalue argument of
0367     // type T will be required.
0368     //
0369     // @group PropertyHelpers {
0370     template <class F>
0371     object make_getter(F f)
0372     {
0373         typedef typename api::is_object_operators<F>::type is_obj_or_proxy;
0374         
0375         return objects::add_doc(
0376             this->make_fn_impl(
0377             detail::unwrap_wrapper((W*)0)
0378           , f, is_obj_or_proxy(), (char*)0, detail::is_data_member_pointer<F>()
0379         ), NULL);
0380     }
0381     
0382     template <class F>
0383     object make_setter(F f)
0384     {
0385         typedef typename api::is_object_operators<F>::type is_obj_or_proxy;
0386         
0387         return objects::add_doc(
0388             this->make_fn_impl(
0389             detail::unwrap_wrapper((W*)0)
0390           , f, is_obj_or_proxy(), (int*)0, detail::is_data_member_pointer<F>()
0391         ), NULL);
0392     }
0393     
0394     template <class T, class F>
0395     object make_fn_impl(T*, F const& f, mpl::false_, void*, mpl::false_)
0396     {
0397         return python::make_function(f, default_call_policies(), detail::get_signature(f, (T*)0));
0398     }
0399 
0400     template <class T, class D, class B>
0401     object make_fn_impl(T*, D B::*pm_, mpl::false_, char*, mpl::true_)
0402     {
0403         D T::*pm = pm_;
0404         return python::make_getter(pm);
0405     }
0406 
0407     template <class T, class D, class B>
0408     object make_fn_impl(T*, D B::*pm_, mpl::false_, int*, mpl::true_)
0409     {
0410         D T::*pm = pm_;
0411         return python::make_setter(pm);
0412     }
0413 
0414     template <class T, class F>
0415     object make_fn_impl(T*, F const& x, mpl::true_, void*, mpl::false_)
0416     {
0417         return x;
0418     }
0419     // }
0420     
0421     template <class D, class B>
0422     self& def_readonly_impl(
0423         char const* name, D B::*pm_, char const* doc BOOST_PYTHON_YES_DATA_MEMBER)
0424     {
0425         return this->add_property(name, pm_, doc);
0426     }
0427 
0428     template <class D, class B>
0429     self& def_readwrite_impl(
0430         char const* name, D B::*pm_, char const* doc BOOST_PYTHON_YES_DATA_MEMBER)
0431     {
0432         return this->add_property(name, pm_, pm_, doc);
0433     }
0434 
0435     template <class D>
0436     self& def_readonly_impl(
0437         char const* name, D& d, char const* BOOST_PYTHON_NO_DATA_MEMBER)
0438     {
0439         return this->add_static_property(name, python::make_getter(d));
0440     }
0441 
0442     template <class D>
0443     self& def_readwrite_impl(
0444         char const* name, D& d, char const* BOOST_PYTHON_NO_DATA_MEMBER)
0445     {
0446         return this->add_static_property(name, python::make_getter(d), python::make_setter(d));
0447     }
0448 
0449     template <class DefVisitor>
0450     inline void initialize(DefVisitor const& i)
0451     {
0452         metadata::register_(); // set up runtime metadata/conversions
0453         
0454         typedef typename metadata::holder holder;
0455         this->set_instance_size( objects::additional_instance_size<holder>::value );
0456         
0457         this->def(i);
0458     }
0459     
0460     inline void initialize(no_init_t)
0461     {
0462         metadata::register_(); // set up runtime metadata/conversions
0463         this->def_no_init();
0464     }
0465     
0466     //
0467     // These two overloads discriminate between def() as applied to a
0468     // generic visitor and everything else.
0469     //
0470     // @group def_impl {
0471     template <class T, class Helper, class LeafVisitor, class Visitor>
0472     inline void def_impl(
0473         T*
0474       , char const* name
0475       , LeafVisitor
0476       , Helper const& helper
0477       , def_visitor<Visitor> const* v
0478     )
0479     {
0480         v->visit(*this, name,  helper);
0481     }
0482 
0483     template <class T, class Fn, class Helper>
0484     inline void def_impl(
0485         T*
0486       , char const* name
0487       , Fn fn
0488       , Helper const& helper
0489       , ...
0490     )
0491     {
0492         objects::add_to_namespace(
0493             *this
0494           , name
0495           , make_function(
0496                 fn
0497               , helper.policies()
0498               , helper.keywords()
0499               , detail::get_signature(fn, (T*)0)
0500             )
0501           , helper.doc()
0502         );
0503 
0504         this->def_default(name, fn, helper, mpl::bool_<Helper::has_default_implementation>());
0505     }
0506     // }
0507 
0508     //
0509     // These two overloads handle the definition of default
0510     // implementation overloads for virtual functions. The second one
0511     // handles the case where no default implementation was specified.
0512     //
0513     // @group def_default {
0514     template <class Fn, class Helper>
0515     inline void def_default(
0516         char const* name
0517         , Fn
0518         , Helper const& helper
0519         , mpl::bool_<true>)
0520     {
0521         detail::error::virtual_function_default<W,Fn>::must_be_derived_class_member(
0522             helper.default_implementation());
0523             
0524         objects::add_to_namespace(
0525             *this, name,
0526             make_function(
0527                 helper.default_implementation(), helper.policies(), helper.keywords())
0528             );
0529     }
0530     
0531     template <class Fn, class Helper>
0532     inline void def_default(char const*, Fn, Helper const&, mpl::bool_<false>)
0533     { }
0534     // }
0535     
0536     //
0537     // These two overloads discriminate between def() as applied to
0538     // regular functions and def() as applied to the result of
0539     // BOOST_PYTHON_FUNCTION_OVERLOADS(). The final argument is used to
0540     // discriminate.
0541     //
0542     // @group def_maybe_overloads {
0543     template <class OverloadsT, class SigT>
0544     void def_maybe_overloads(
0545         char const* name
0546         , SigT sig
0547         , OverloadsT const& overloads
0548         , detail::overloads_base const*)
0549 
0550     {
0551         //  convert sig to a type_list (see detail::get_signature in signature.hpp)
0552         //  before calling detail::define_with_defaults.
0553         detail::define_with_defaults(
0554             name, overloads, *this, detail::get_signature(sig));
0555     }
0556 
0557     template <class Fn, class A1>
0558     void def_maybe_overloads(
0559         char const* name
0560         , Fn fn
0561         , A1 const& a1
0562         , ...)
0563     {
0564         this->def_impl(
0565             detail::unwrap_wrapper((W*)0)
0566           , name
0567           , fn
0568           , detail::def_helper<A1>(a1)
0569           , &fn
0570         );
0571 
0572     }
0573     // }
0574 };
0575 
0576 
0577 //
0578 // implementations
0579 //
0580 
0581 template <class W, class X1, class X2, class X3>
0582 inline class_<W,X1,X2,X3>::class_(char const* name, char const* doc)
0583     : base(name, id_vector::size, id_vector().ids, doc)
0584 {
0585     this->initialize(init<>());
0586 //  select_holder::assert_default_constructible();
0587 }
0588 
0589 template <class W, class X1, class X2, class X3>
0590 inline class_<W,X1,X2,X3>::class_(char const* name, no_init_t)
0591     : base(name, id_vector::size, id_vector().ids)
0592 {
0593     this->initialize(no_init);
0594 }
0595 
0596 template <class W, class X1, class X2, class X3>
0597 inline class_<W,X1,X2,X3>::class_(char const* name, char const* doc, no_init_t)
0598     : base(name, id_vector::size, id_vector().ids, doc)
0599 {
0600     this->initialize(no_init);
0601 }
0602 
0603 }} // namespace boost::python
0604 
0605 # undef BOOST_PYTHON_DATA_MEMBER_HELPER
0606 # undef BOOST_PYTHON_YES_DATA_MEMBER
0607 # undef BOOST_PYTHON_NO_DATA_MEMBER
0608 # undef BOOST_PYTHON_NO_MEMBER_POINTER_ORDERING
0609 
0610 #endif // CLASS_DWA200216_HPP