Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-19 09:46:09

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 this->make_fn_impl(
0376             detail::unwrap_wrapper((W*)0)
0377           , f, is_obj_or_proxy(), (char*)0, detail::is_data_member_pointer<F>()
0378         );
0379     }
0380     
0381     template <class F>
0382     object make_setter(F f)
0383     {
0384         typedef typename api::is_object_operators<F>::type is_obj_or_proxy;
0385         
0386         return this->make_fn_impl(
0387             detail::unwrap_wrapper((W*)0)
0388           , f, is_obj_or_proxy(), (int*)0, detail::is_data_member_pointer<F>()
0389         );
0390     }
0391     
0392     template <class T, class F>
0393     object make_fn_impl(T*, F const& f, mpl::false_, void*, mpl::false_)
0394     {
0395         return python::make_function(f, default_call_policies(), detail::get_signature(f, (T*)0));
0396     }
0397 
0398     template <class T, class D, class B>
0399     object make_fn_impl(T*, D B::*pm_, mpl::false_, char*, mpl::true_)
0400     {
0401         D T::*pm = pm_;
0402         return python::make_getter(pm);
0403     }
0404 
0405     template <class T, class D, class B>
0406     object make_fn_impl(T*, D B::*pm_, mpl::false_, int*, mpl::true_)
0407     {
0408         D T::*pm = pm_;
0409         return python::make_setter(pm);
0410     }
0411 
0412     template <class T, class F>
0413     object make_fn_impl(T*, F const& x, mpl::true_, void*, mpl::false_)
0414     {
0415         return x;
0416     }
0417     // }
0418     
0419     template <class D, class B>
0420     self& def_readonly_impl(
0421         char const* name, D B::*pm_, char const* doc BOOST_PYTHON_YES_DATA_MEMBER)
0422     {
0423         return this->add_property(name, pm_, doc);
0424     }
0425 
0426     template <class D, class B>
0427     self& def_readwrite_impl(
0428         char const* name, D B::*pm_, char const* doc BOOST_PYTHON_YES_DATA_MEMBER)
0429     {
0430         return this->add_property(name, pm_, pm_, doc);
0431     }
0432 
0433     template <class D>
0434     self& def_readonly_impl(
0435         char const* name, D& d, char const* BOOST_PYTHON_NO_DATA_MEMBER)
0436     {
0437         return this->add_static_property(name, python::make_getter(d));
0438     }
0439 
0440     template <class D>
0441     self& def_readwrite_impl(
0442         char const* name, D& d, char const* BOOST_PYTHON_NO_DATA_MEMBER)
0443     {
0444         return this->add_static_property(name, python::make_getter(d), python::make_setter(d));
0445     }
0446 
0447     template <class DefVisitor>
0448     inline void initialize(DefVisitor const& i)
0449     {
0450         metadata::register_(); // set up runtime metadata/conversions
0451         
0452         typedef typename metadata::holder holder;
0453         this->set_instance_size( objects::additional_instance_size<holder>::value );
0454         
0455         this->def(i);
0456     }
0457     
0458     inline void initialize(no_init_t)
0459     {
0460         metadata::register_(); // set up runtime metadata/conversions
0461         this->def_no_init();
0462     }
0463     
0464     //
0465     // These two overloads discriminate between def() as applied to a
0466     // generic visitor and everything else.
0467     //
0468     // @group def_impl {
0469     template <class T, class Helper, class LeafVisitor, class Visitor>
0470     inline void def_impl(
0471         T*
0472       , char const* name
0473       , LeafVisitor
0474       , Helper const& helper
0475       , def_visitor<Visitor> const* v
0476     )
0477     {
0478         v->visit(*this, name,  helper);
0479     }
0480 
0481     template <class T, class Fn, class Helper>
0482     inline void def_impl(
0483         T*
0484       , char const* name
0485       , Fn fn
0486       , Helper const& helper
0487       , ...
0488     )
0489     {
0490         objects::add_to_namespace(
0491             *this
0492           , name
0493           , make_function(
0494                 fn
0495               , helper.policies()
0496               , helper.keywords()
0497               , detail::get_signature(fn, (T*)0)
0498             )
0499           , helper.doc()
0500         );
0501 
0502         this->def_default(name, fn, helper, mpl::bool_<Helper::has_default_implementation>());
0503     }
0504     // }
0505 
0506     //
0507     // These two overloads handle the definition of default
0508     // implementation overloads for virtual functions. The second one
0509     // handles the case where no default implementation was specified.
0510     //
0511     // @group def_default {
0512     template <class Fn, class Helper>
0513     inline void def_default(
0514         char const* name
0515         , Fn
0516         , Helper const& helper
0517         , mpl::bool_<true>)
0518     {
0519         detail::error::virtual_function_default<W,Fn>::must_be_derived_class_member(
0520             helper.default_implementation());
0521             
0522         objects::add_to_namespace(
0523             *this, name,
0524             make_function(
0525                 helper.default_implementation(), helper.policies(), helper.keywords())
0526             );
0527     }
0528     
0529     template <class Fn, class Helper>
0530     inline void def_default(char const*, Fn, Helper const&, mpl::bool_<false>)
0531     { }
0532     // }
0533     
0534     //
0535     // These two overloads discriminate between def() as applied to
0536     // regular functions and def() as applied to the result of
0537     // BOOST_PYTHON_FUNCTION_OVERLOADS(). The final argument is used to
0538     // discriminate.
0539     //
0540     // @group def_maybe_overloads {
0541     template <class OverloadsT, class SigT>
0542     void def_maybe_overloads(
0543         char const* name
0544         , SigT sig
0545         , OverloadsT const& overloads
0546         , detail::overloads_base const*)
0547 
0548     {
0549         //  convert sig to a type_list (see detail::get_signature in signature.hpp)
0550         //  before calling detail::define_with_defaults.
0551         detail::define_with_defaults(
0552             name, overloads, *this, detail::get_signature(sig));
0553     }
0554 
0555     template <class Fn, class A1>
0556     void def_maybe_overloads(
0557         char const* name
0558         , Fn fn
0559         , A1 const& a1
0560         , ...)
0561     {
0562         this->def_impl(
0563             detail::unwrap_wrapper((W*)0)
0564           , name
0565           , fn
0566           , detail::def_helper<A1>(a1)
0567           , &fn
0568         );
0569 
0570     }
0571     // }
0572 };
0573 
0574 
0575 //
0576 // implementations
0577 //
0578 
0579 template <class W, class X1, class X2, class X3>
0580 inline class_<W,X1,X2,X3>::class_(char const* name, char const* doc)
0581     : base(name, id_vector::size, id_vector().ids, doc)
0582 {
0583     this->initialize(init<>());
0584 //  select_holder::assert_default_constructible();
0585 }
0586 
0587 template <class W, class X1, class X2, class X3>
0588 inline class_<W,X1,X2,X3>::class_(char const* name, no_init_t)
0589     : base(name, id_vector::size, id_vector().ids)
0590 {
0591     this->initialize(no_init);
0592 }
0593 
0594 template <class W, class X1, class X2, class X3>
0595 inline class_<W,X1,X2,X3>::class_(char const* name, char const* doc, no_init_t)
0596     : base(name, id_vector::size, id_vector().ids, doc)
0597 {
0598     this->initialize(no_init);
0599 }
0600 
0601 }} // namespace boost::python
0602 
0603 # undef BOOST_PYTHON_DATA_MEMBER_HELPER
0604 # undef BOOST_PYTHON_YES_DATA_MEMBER
0605 # undef BOOST_PYTHON_NO_DATA_MEMBER
0606 # undef BOOST_PYTHON_NO_MEMBER_POINTER_ORDERING
0607 
0608 #endif // CLASS_DWA200216_HPP