mirror of
https://github.com/boostorg/python.git
synced 2026-01-22 17:32:55 +00:00
more implicit conversion work
[SVN r13282]
This commit is contained in:
@@ -37,7 +37,7 @@ struct implicit
|
||||
registration->construct(obj, &intermediate_data.stage1);
|
||||
|
||||
void* storage = ((rvalue_base_data<Target>*)data)->storage.bytes;
|
||||
new (storage) Target(*(Source*)intermediate_data.storage.bytes);
|
||||
new (storage) Target(*static_cast<Source*>(intermediate_data.stage1.convertible));
|
||||
|
||||
// record successful construction
|
||||
data->convertible = storage;
|
||||
|
||||
@@ -37,6 +37,14 @@ namespace registry
|
||||
, undecorated_type_id_t
|
||||
);
|
||||
|
||||
// Insert an rvalue from_python converter at the tail of the
|
||||
// chain. Used for implicit conversions
|
||||
BOOST_PYTHON_DECL void push_back(
|
||||
void* (*convertible)(PyObject*)
|
||||
, constructor_function
|
||||
, undecorated_type_id_t
|
||||
);
|
||||
|
||||
BOOST_PYTHON_DECL PyTypeObject*& class_object(undecorated_type_id_t key);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ void implicitly_convertible(boost::type<Source>* = 0, boost::type<Target>* = 0)
|
||||
{
|
||||
typedef converter::implicit<Source,Target> functions;
|
||||
|
||||
converter::registry::insert(
|
||||
converter::registry::push_back(
|
||||
&functions::convertible
|
||||
, &functions::construct
|
||||
, converter::undecorated_type_id<Target>());
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#include <boost/python/converter/find_from_python.hpp>
|
||||
#include <boost/python/converter/registrations.hpp>
|
||||
#include <boost/python/converter/from_python_data.hpp>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
@@ -29,15 +31,38 @@ BOOST_PYTHON_DECL rvalue_stage1_data find(
|
||||
return data;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
// Prevent looping in implicit conversions. This could/should be
|
||||
// much more efficient, but will work for now.
|
||||
typedef std::vector<rvalue_from_python_registration const*> visited_t;
|
||||
static visited_t visited;
|
||||
}
|
||||
|
||||
BOOST_PYTHON_DECL rvalue_from_python_registration const* find_chain(
|
||||
PyObject* source
|
||||
, rvalue_from_python_registration const* chain)
|
||||
{
|
||||
for (;chain != 0; chain = chain->next)
|
||||
{
|
||||
visited_t::iterator p = std::lower_bound(visited.begin(), visited.end(), chain);
|
||||
if (p != visited.end() && *p == chain)
|
||||
return 0;
|
||||
|
||||
visited.insert(p, chain);
|
||||
try
|
||||
{
|
||||
if (chain->convertible(source))
|
||||
break;
|
||||
for (;chain != 0; chain = chain->next)
|
||||
{
|
||||
if (chain->convertible(source))
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
visited.erase(p);
|
||||
throw;
|
||||
}
|
||||
p = std::lower_bound(visited.begin(), visited.end(), chain);
|
||||
visited.erase(p);
|
||||
return chain;
|
||||
}
|
||||
|
||||
|
||||
@@ -109,6 +109,22 @@ namespace registry
|
||||
found->m_rvalue_from_python = registration;
|
||||
}
|
||||
|
||||
// Insert an rvalue from_python converter
|
||||
void push_back(void* (*convertible)(PyObject*)
|
||||
, constructor_function construct
|
||||
, undecorated_type_id_t key)
|
||||
{
|
||||
rvalue_from_python_registration** found = &find(key)->m_rvalue_from_python;
|
||||
while (*found != 0)
|
||||
found = &(*found)->next;
|
||||
|
||||
rvalue_from_python_registration *registration = new rvalue_from_python_registration;
|
||||
registration->convertible = convertible;
|
||||
registration->construct = construct;
|
||||
registration->next = 0;
|
||||
*found = registration;
|
||||
}
|
||||
|
||||
PyTypeObject*& class_object(undecorated_type_id_t key)
|
||||
{
|
||||
return find(key)->m_class_object;
|
||||
|
||||
@@ -14,24 +14,35 @@
|
||||
using namespace boost::python;
|
||||
|
||||
typedef test_class<> X;
|
||||
typedef test_class<1> Y;
|
||||
|
||||
int x_value(X const& x)
|
||||
{
|
||||
return x.value();
|
||||
}
|
||||
|
||||
X make_x(int n) { return X(n); }
|
||||
|
||||
BOOST_PYTHON_MODULE_INIT(implicit_ext)
|
||||
{
|
||||
implicitly_convertible<int,X>();
|
||||
module("implicit_ext")
|
||||
.def("x_value", x_value)
|
||||
.def("make_x", make_x)
|
||||
.add(
|
||||
class_<X>("X")
|
||||
.def_init(args<int>())
|
||||
.def("value", &X::value)
|
||||
.def("set", &X::set)
|
||||
)
|
||||
.add(
|
||||
class_<Y>("Y")
|
||||
.def_init(args<int>())
|
||||
.def("value", &Y::value)
|
||||
.def("set", &Y::set)
|
||||
)
|
||||
;
|
||||
implicitly_convertible<X,int>();
|
||||
}
|
||||
|
||||
#include "module_tail.cpp"
|
||||
|
||||
@@ -4,6 +4,12 @@
|
||||
42
|
||||
>>> x_value(42)
|
||||
42
|
||||
>>> x = make_x(X(42))
|
||||
>>> x.value()
|
||||
42
|
||||
>>> try: make_x('fool')
|
||||
... except TypeError: pass
|
||||
... else: print 'no error'
|
||||
'''
|
||||
|
||||
def run(args = None):
|
||||
|
||||
@@ -16,6 +16,7 @@ struct test_class
|
||||
|
||||
void set(int x) { assert(magic == 7654321 + n); this->x = x; }
|
||||
int value() const { assert(magic == 7654321 + n); return x; }
|
||||
operator int() const { return x; }
|
||||
static int count() { return counter; }
|
||||
private:
|
||||
void operator=(test_class const&);
|
||||
|
||||
Reference in New Issue
Block a user