mirror of
https://github.com/boostorg/python.git
synced 2026-01-31 20:32:16 +00:00
Use def_visitor to simplify class def(...) handling.
Workarounds for intel6 and vc6. [SVN r19533]
This commit is contained in:
@@ -38,7 +38,6 @@
|
||||
# include <boost/python/object/add_to_namespace.hpp>
|
||||
# include <boost/python/object/class_converters.hpp>
|
||||
|
||||
# include <boost/python/detail/string_literal.hpp>
|
||||
# include <boost/python/detail/overloads_fwd.hpp>
|
||||
# include <boost/python/detail/operator_id.hpp>
|
||||
# include <boost/python/detail/member_function_cast.hpp>
|
||||
@@ -59,11 +58,9 @@
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
enum no_init_t { no_init };
|
||||
template <class DerivedVisitor> struct def_visitor;
|
||||
|
||||
struct def_arg_base {};
|
||||
template <class Derived>
|
||||
struct def_arg : def_arg_base {}; // Generic visitor
|
||||
enum no_init_t { no_init };
|
||||
|
||||
namespace detail
|
||||
{
|
||||
@@ -90,9 +87,6 @@ namespace detail
|
||||
template <class T1, class T2, class T3>
|
||||
struct has_noncopyable;
|
||||
|
||||
template <detail::operator_id, class L, class R>
|
||||
struct operator_;
|
||||
|
||||
// Register to_python converters for a class T. The first argument
|
||||
// will be mpl::true_ unless noncopyable was specified as a
|
||||
// class_<...> template parameter. The 2nd argument is a pointer to
|
||||
@@ -249,7 +243,7 @@ class class_ : public objects::class_base
|
||||
: base(name, id_vector::size, id_vector().ids)
|
||||
{
|
||||
this->register_();
|
||||
define_init(*this, i.derived());
|
||||
this->def(i);
|
||||
this->set_instance_size(holder_selector::additional_size());
|
||||
}
|
||||
|
||||
@@ -259,26 +253,18 @@ class class_ : public objects::class_base
|
||||
: base(name, id_vector::size, id_vector().ids, doc)
|
||||
{
|
||||
this->register_();
|
||||
define_init(*this, i.derived());
|
||||
this->def(i);
|
||||
this->set_instance_size(holder_selector::additional_size());
|
||||
}
|
||||
|
||||
public: // member functions
|
||||
|
||||
// Define additional constructors
|
||||
template <class DerivedT>
|
||||
self& def(init_base<DerivedT> const& i)
|
||||
{
|
||||
define_init(*this, i.derived());
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Generic visitation
|
||||
template <class Derived>
|
||||
self& def(def_arg<Derived> const& visitor)
|
||||
self& def(def_visitor<Derived> const& visitor)
|
||||
{
|
||||
static_cast<Derived const&>(visitor).visit(*this);
|
||||
return *this;
|
||||
visitor.visit(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Wrap a member function or a non-member function which can take
|
||||
@@ -324,13 +310,6 @@ class class_ : public objects::class_base
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <detail::operator_id id, class L, class R>
|
||||
self& def(detail::operator_<id,L,R> const& op)
|
||||
{
|
||||
typedef detail::operator_<id,L,R> op_t;
|
||||
return this->def(op.name(), &op_t::template apply<T>::execute);
|
||||
}
|
||||
|
||||
//
|
||||
// Data member access
|
||||
//
|
||||
@@ -476,42 +455,27 @@ class class_ : public objects::class_base
|
||||
inline void register_() const;
|
||||
|
||||
//
|
||||
// These three overloads discriminate between def() as applied to
|
||||
// things which are already wrapped into callable python::object
|
||||
// instances, a generic visitor, and everything else.
|
||||
// These two overloads discriminate between def() as applied to a
|
||||
// generic visitor and everything else.
|
||||
//
|
||||
template <class F, class A1>
|
||||
template <class Helper, class LeafVisitor, class Visitor>
|
||||
inline void def_impl(
|
||||
char const* name
|
||||
, F f
|
||||
, detail::def_helper<A1> const& helper
|
||||
, object const*)
|
||||
, LeafVisitor
|
||||
, Helper const& helper
|
||||
, def_visitor<Visitor> const* v
|
||||
)
|
||||
{
|
||||
// It's too late to specify anything other than docstrings, if
|
||||
// the callable object is already wrapped.
|
||||
BOOST_STATIC_ASSERT(
|
||||
(is_same<char const*,A1>::value
|
||||
|| detail::is_string_literal<A1>::value));
|
||||
|
||||
objects::add_to_namespace(*this, name, f, helper.doc());
|
||||
v->visit(*this, name, helper);
|
||||
}
|
||||
|
||||
template <class Derived, class A1>
|
||||
inline void def_impl(
|
||||
char const* name
|
||||
, def_arg<Derived> const& visitor
|
||||
, detail::def_helper<A1> const& helper
|
||||
, def_arg_base const*)
|
||||
{
|
||||
static_cast<Derived const&>(visitor).visit(*this, name);
|
||||
}
|
||||
|
||||
template <class Fn, class Helper>
|
||||
inline void def_impl(
|
||||
char const* name
|
||||
, Fn fn
|
||||
, Helper const& helper
|
||||
, ...)
|
||||
, Fn fn
|
||||
, Helper const& helper
|
||||
, ...
|
||||
)
|
||||
{
|
||||
objects::add_to_namespace(
|
||||
*this, name,
|
||||
@@ -578,9 +542,11 @@ class class_ : public objects::class_base
|
||||
, ...)
|
||||
{
|
||||
this->def_impl(
|
||||
name, fn
|
||||
, detail::def_helper<A1>(a1)
|
||||
, &fn);
|
||||
name
|
||||
, fn
|
||||
, detail::def_helper<A1>(a1)
|
||||
, &fn
|
||||
);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
87
include/boost/python/def_visitor.hpp
Executable file
87
include/boost/python/def_visitor.hpp
Executable file
@@ -0,0 +1,87 @@
|
||||
// Copyright David Abrahams 2003. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef DEF_VISITOR_DWA2003810_HPP
|
||||
# define DEF_VISITOR_DWA2003810_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
# include <boost/detail/workaround.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
template <class DerivedVisitor> class def_visitor;
|
||||
template <class T, class X1, class X2, class X3> class class_;
|
||||
|
||||
class def_visitor_access
|
||||
{
|
||||
# if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) \
|
||||
|| BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
|
||||
// Tasteless as this may seem, making all members public allows member templates
|
||||
// to work in the absence of member template friends.
|
||||
public:
|
||||
# else
|
||||
template <class Derived> friend class def_visitor;
|
||||
# endif
|
||||
|
||||
// unnamed visit, c.f. init<...>, container suites
|
||||
template <class V, class classT>
|
||||
static void visit(V const& v, classT& c)
|
||||
{
|
||||
v.derived_visitor().visit(c);
|
||||
}
|
||||
|
||||
// named visit, c.f. object, pure_virtual
|
||||
template <class V, class classT, class OptionalArgs>
|
||||
static void visit(
|
||||
V const& v
|
||||
, classT& c
|
||||
, char const* name
|
||||
, OptionalArgs const& options
|
||||
)
|
||||
{
|
||||
v.derived_visitor().visit(c, name, options);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
template <class DerivedVisitor>
|
||||
class def_visitor
|
||||
{
|
||||
friend class def_visitor_access;
|
||||
|
||||
# if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) \
|
||||
|| BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
|
||||
// Tasteless as this may seem, making all members public allows member templates
|
||||
// to work in the absence of member template friends.
|
||||
public:
|
||||
# else
|
||||
template <class T, class X1, class X2, class X3> friend class class_;
|
||||
# endif
|
||||
|
||||
// unnamed visit, c.f. init<...>, container suites
|
||||
template <class classT>
|
||||
void visit(classT& c) const
|
||||
{
|
||||
def_visitor_access::visit(*this, c);
|
||||
}
|
||||
|
||||
// named visit, c.f. object, pure_virtual
|
||||
template <class classT, class OptionalArgs>
|
||||
void visit(classT& c, char const* name, OptionalArgs const& options) const
|
||||
{
|
||||
def_visitor_access::visit(*this, c, name, options);
|
||||
}
|
||||
|
||||
protected:
|
||||
DerivedVisitor const& derived_visitor() const
|
||||
{
|
||||
return static_cast<DerivedVisitor const&>(*this);
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // DEF_VISITOR_DWA2003810_HPP
|
||||
@@ -18,6 +18,7 @@
|
||||
# include <boost/mpl/apply.hpp>
|
||||
# include <boost/tuple/tuple.hpp>
|
||||
# include <boost/python/detail/not_specified.hpp>
|
||||
# include <boost/python/detail/def_helper_fwd.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
@@ -143,7 +144,7 @@ namespace detail
|
||||
// are expected to be the types of the actual (optional) arguments
|
||||
// passed to def().
|
||||
//
|
||||
template <class T1, class T2 = not_specified, class T3 = not_specified, class T4 = not_specified>
|
||||
template <class T1, class T2, class T3, class T4>
|
||||
struct def_helper
|
||||
{
|
||||
// A tuple type which begins with references to the supplied
|
||||
|
||||
18
include/boost/python/detail/def_helper_fwd.hpp
Executable file
18
include/boost/python/detail/def_helper_fwd.hpp
Executable file
@@ -0,0 +1,18 @@
|
||||
// Copyright David Abrahams 2003. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef DEF_HELPER_FWD_DWA2003810_HPP
|
||||
# define DEF_HELPER_FWD_DWA2003810_HPP
|
||||
|
||||
# include <boost/python/detail/not_specified.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace detail {
|
||||
|
||||
template <class T1, class T2 = not_specified, class T3 = not_specified, class T4 = not_specified>
|
||||
struct def_helper;
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
#endif // DEF_HELPER_FWD_DWA2003810_HPP
|
||||
@@ -7,7 +7,7 @@
|
||||
#ifndef INDEXING_SUITE_JDG20036_HPP
|
||||
# define INDEXING_SUITE_JDG20036_HPP
|
||||
|
||||
# include <boost/python/class.hpp>
|
||||
# include <boost/python/def_visitor.hpp>
|
||||
# include <boost/python/register_ptr_to_python.hpp>
|
||||
# include <boost/python/indexing/detail/indexing_suite_detail.hpp>
|
||||
# include <boost/python/indexing/py_container_utils.hpp>
|
||||
@@ -105,7 +105,7 @@ namespace boost { namespace python {
|
||||
, class Index = typename Container::size_type
|
||||
>
|
||||
class indexing_suite
|
||||
: public def_arg<
|
||||
: public def_visitor<
|
||||
indexing_suite<
|
||||
Container
|
||||
, DerivedPolicies
|
||||
@@ -162,7 +162,7 @@ namespace boost { namespace python {
|
||||
, Index> >::type
|
||||
slice_handler;
|
||||
|
||||
public:
|
||||
private: // def visitation
|
||||
|
||||
template <class Class>
|
||||
void visit(Class& cl) const
|
||||
@@ -183,7 +183,9 @@ namespace boost { namespace python {
|
||||
;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class python::def_visitor_access;
|
||||
|
||||
private:
|
||||
|
||||
static object
|
||||
base_get_item(back_reference<Container&> container, PyObject* i)
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <boost/python/detail/type_list.hpp>
|
||||
#include <boost/python/args_fwd.hpp>
|
||||
#include <boost/python/detail/make_keyword_range_fn.hpp>
|
||||
#include <boost/python/def_visitor.hpp>
|
||||
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/apply_if.hpp>
|
||||
@@ -110,10 +111,13 @@ namespace detail
|
||||
|
||||
#endif
|
||||
|
||||
template <int NDefaults>
|
||||
struct define_class_init_helper;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class DerivedT>
|
||||
struct init_base
|
||||
struct init_base : def_visitor<DerivedT>
|
||||
{
|
||||
init_base(char const* doc_, detail::keyword_range const& keywords_)
|
||||
: m_doc(doc_), m_keywords(keywords_)
|
||||
@@ -122,7 +126,7 @@ struct init_base
|
||||
init_base(char const* doc_)
|
||||
: m_doc(doc_)
|
||||
{}
|
||||
|
||||
|
||||
DerivedT const& derived() const
|
||||
{
|
||||
return *static_cast<DerivedT const*>(this);
|
||||
@@ -142,6 +146,39 @@ struct init_base
|
||||
{
|
||||
return default_call_policies();
|
||||
}
|
||||
|
||||
private:
|
||||
// visit
|
||||
//
|
||||
// Defines a set of n_defaults + 1 constructors for its
|
||||
// class_<...> argument. Each constructor after the first has
|
||||
// one less argument to its right. Example:
|
||||
//
|
||||
// init<int, optional<char, long, double> >
|
||||
//
|
||||
// Defines:
|
||||
//
|
||||
// __init__(int, char, long, double)
|
||||
// __init__(int, char, long)
|
||||
// __init__(int, char)
|
||||
// __init__(int)
|
||||
template <class classT>
|
||||
void visit(classT& cl) const
|
||||
{
|
||||
typedef typename DerivedT::signature signature;
|
||||
typedef typename DerivedT::n_arguments n_arguments;
|
||||
typedef typename DerivedT::n_defaults n_defaults;
|
||||
|
||||
detail::define_class_init_helper<n_defaults::value>::apply(
|
||||
cl
|
||||
, derived().call_policies()
|
||||
, signature()
|
||||
, n_arguments()
|
||||
, derived().doc_string()
|
||||
, derived().keywords());
|
||||
}
|
||||
|
||||
friend class python::def_visitor_access;
|
||||
|
||||
private: // data members
|
||||
char const* m_doc;
|
||||
@@ -326,7 +363,8 @@ namespace detail
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <int NDefaults>
|
||||
struct define_class_init_helper {
|
||||
struct define_class_init_helper
|
||||
{
|
||||
|
||||
template <class ClassT, class CallPoliciesT, class Signature, class NArgs>
|
||||
static void apply(
|
||||
@@ -375,39 +413,6 @@ namespace detail
|
||||
};
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// define_init
|
||||
//
|
||||
// Accepts a class_ and an init-list. Defines a set of constructors for
|
||||
// the class given the arguments. The init list (see init above) has
|
||||
// n_defaults (number of default arguments and n_arguments (number of
|
||||
// actual arguments). This function defines n_defaults + 1 constructors
|
||||
// for the class. Each constructor after the first has one less argument
|
||||
// to its right. Example:
|
||||
//
|
||||
// init<int, default<char, long, double>
|
||||
//
|
||||
// Defines:
|
||||
//
|
||||
// __init__(int, char, long, double)
|
||||
// __init__(int, char, long)
|
||||
// __init__(int, char)
|
||||
// __init__(int)
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <class ClassT, class InitT>
|
||||
void
|
||||
define_init(ClassT& cl, InitT const& i)
|
||||
{
|
||||
typedef typename InitT::signature signature;
|
||||
typedef typename InitT::n_arguments n_arguments;
|
||||
typedef typename InitT::n_defaults n_defaults;
|
||||
|
||||
detail::define_class_init_helper<n_defaults::value>::apply(
|
||||
cl, i.call_policies(), signature(), n_arguments(), i.doc_string(), i.keywords());
|
||||
}
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#undef BOOST_PYTHON_OVERLOAD_TYPES_WITH_DEFAULT
|
||||
|
||||
@@ -17,16 +17,22 @@
|
||||
# include <boost/python/refcount.hpp>
|
||||
# include <boost/python/detail/preprocessor.hpp>
|
||||
# include <boost/python/tag.hpp>
|
||||
# include <boost/python/def_visitor.hpp>
|
||||
|
||||
# include <boost/python/detail/raw_pyobject.hpp>
|
||||
# include <boost/python/detail/dependent.hpp>
|
||||
|
||||
# include <boost/python/object/forward.hpp>
|
||||
# include <boost/python/object/add_to_namespace.hpp>
|
||||
|
||||
# include <boost/preprocessor/iterate.hpp>
|
||||
# include <boost/preprocessor/debug/line.hpp>
|
||||
# include <boost/python/detail/is_xxx.hpp>
|
||||
|
||||
# include <boost/type_traits/is_same.hpp>
|
||||
# include <boost/python/detail/string_literal.hpp>
|
||||
# include <boost/python/detail/def_helper_fwd.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace converter
|
||||
@@ -69,7 +75,7 @@ namespace api
|
||||
typedef PyObject* (object::*bool_type)() const;
|
||||
|
||||
template <class U>
|
||||
class object_operators
|
||||
class object_operators : public def_visitor<U>
|
||||
{
|
||||
protected:
|
||||
# if !defined(BOOST_MSVC) || BOOST_MSVC > 1200
|
||||
@@ -157,7 +163,23 @@ namespace api
|
||||
slice_bound<T>::type(start)
|
||||
, slice_bound<V>::type(end));
|
||||
}
|
||||
# endif
|
||||
# endif
|
||||
|
||||
private: // def visitation for adding callable objects as class methods
|
||||
template <class ClassT, class DocStringT>
|
||||
void visit(ClassT& cl, char const* name, python::detail::def_helper<DocStringT> const& helper) const
|
||||
{
|
||||
// It's too late to specify anything other than docstrings if
|
||||
// the callable object is already wrapped.
|
||||
BOOST_STATIC_ASSERT(
|
||||
(is_same<char const*,DocStringT>::value
|
||||
|| detail::is_string_literal<DocStringT>::value));
|
||||
|
||||
objects::add_to_namespace(cl, name, this->derived_visitor(), helper.doc());
|
||||
}
|
||||
|
||||
friend class python::def_visitor_access;
|
||||
|
||||
private:
|
||||
// there is a confirmed CWPro8 codegen bug here. We prevent the
|
||||
// early destruction of a temporary by binding a named object
|
||||
|
||||
@@ -8,11 +8,13 @@
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
|
||||
# include <boost/python/def_visitor.hpp>
|
||||
# include <boost/python/converter/arg_to_python.hpp>
|
||||
# include <boost/python/detail/operator_id.hpp>
|
||||
# include <boost/python/detail/not_specified.hpp>
|
||||
# include <boost/python/back_reference.hpp>
|
||||
# include <boost/mpl/if.hpp>
|
||||
# include <boost/mpl/apply_if.hpp>
|
||||
# include <boost/python/self.hpp>
|
||||
# include <boost/python/other.hpp>
|
||||
# include <boost/lexical_cast.hpp>
|
||||
@@ -121,20 +123,41 @@ namespace detail
|
||||
// self_t
|
||||
template <operator_id id, class L = not_specified, class R = not_specified>
|
||||
struct operator_
|
||||
: mpl::if_<
|
||||
is_same<L,self_t>
|
||||
, typename mpl::if_<
|
||||
is_same<R,self_t>
|
||||
, binary_op<id>
|
||||
, binary_op_l<id,typename unwrap_other<R>::type>
|
||||
>::type
|
||||
, typename mpl::if_<
|
||||
is_same<L,not_specified>
|
||||
, unary_op<id>
|
||||
, binary_op_r<id,typename unwrap_other<L>::type>
|
||||
>::type
|
||||
>::type
|
||||
: def_visitor<operator_<id,L,R> >
|
||||
{
|
||||
private:
|
||||
template <class ClassT>
|
||||
void visit(ClassT& cl) const
|
||||
{
|
||||
typedef typename mpl::apply_if<
|
||||
is_same<L,self_t>
|
||||
, mpl::if_<
|
||||
is_same<R,self_t>
|
||||
, binary_op<id>
|
||||
, binary_op_l<
|
||||
id
|
||||
, BOOST_DEDUCED_TYPENAME unwrap_other<R>::type
|
||||
>
|
||||
>
|
||||
, mpl::if_<
|
||||
is_same<L,not_specified>
|
||||
, unary_op<id>
|
||||
, binary_op_r<
|
||||
id
|
||||
, BOOST_DEDUCED_TYPENAME unwrap_other<L>::type
|
||||
>
|
||||
>
|
||||
>::type generator;
|
||||
|
||||
cl.def(
|
||||
generator::name()
|
||||
, &generator::template apply<
|
||||
BOOST_DEDUCED_TYPENAME ClassT::wrapped_type
|
||||
>::execute
|
||||
);
|
||||
}
|
||||
|
||||
friend class python::def_visitor_access;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user