2
0
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:
Dave Abrahams
2003-08-11 14:56:30 +00:00
parent d482d57689
commit 9c6650963f
11 changed files with 255 additions and 131 deletions

View File

@@ -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
);
}
};

View 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

View File

@@ -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

View 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

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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;
};
}