New automatic return value policy for cat() and make_tuple(), fixed an ambiguity issue

This commit is contained in:
Wenzel Jakob 2016-04-14 14:26:13 +02:00
parent 2e03a5857c
commit 8bd31c71e4
3 changed files with 16 additions and 5 deletions

View File

@ -418,6 +418,9 @@ functions. The default policy is :enum:`return_value_policy::automatic`.
| :enum:`return_value_policy::automatic` | Automatic: copy objects returned as values and take ownership of | | :enum:`return_value_policy::automatic` | Automatic: copy objects returned as values and take ownership of |
| | objects returned as pointers | | | objects returned as pointers |
+--------------------------------------------------+---------------------------------------------------------------------------+ +--------------------------------------------------+---------------------------------------------------------------------------+
| :enum:`return_value_policy::automatic_reference` | Automatic variant 2 : copy objects returned as values and reference |
| | objects returned as pointers |
+--------------------------------------------------+---------------------------------------------------------------------------+
| :enum:`return_value_policy::copy` | Create a new copy of the returned object, which will be owned by Python | | :enum:`return_value_policy::copy` | Create a new copy of the returned object, which will be owned by Python |
+--------------------------------------------------+---------------------------------------------------------------------------+ +--------------------------------------------------+---------------------------------------------------------------------------+
| :enum:`return_value_policy::take_ownership` | Reference the existing object and take ownership. Python will call | | :enum:`return_value_policy::take_ownership` | Reference the existing object and take ownership. Python will call |

View File

@ -178,6 +178,8 @@ public:
if (policy == return_value_policy::automatic) if (policy == return_value_policy::automatic)
policy = return_value_policy::take_ownership; policy = return_value_policy::take_ownership;
else if (policy == return_value_policy::automatic_reference)
policy = return_value_policy::reference;
if (policy == return_value_policy::copy) { if (policy == return_value_policy::copy) {
wrapper->value = copy_constructor(wrapper->value); wrapper->value = copy_constructor(wrapper->value);
@ -217,7 +219,7 @@ public:
type_caster() : type_caster_generic(typeid(type)) { } type_caster() : type_caster_generic(typeid(type)) { }
static handle cast(const type &src, return_value_policy policy, handle parent) { static handle cast(const type &src, return_value_policy policy, handle parent) {
if (policy == return_value_policy::automatic) if (policy == return_value_policy::automatic || policy == return_value_policy::automatic_reference)
policy = return_value_policy::copy; policy = return_value_policy::copy;
return cast(&src, policy, parent); return cast(&src, policy, parent);
} }
@ -706,20 +708,23 @@ template <typename T> inline T cast(handle handle) {
return (T) conv; return (T) conv;
} }
template <typename T> inline object cast(const T &value, return_value_policy policy = return_value_policy::automatic, handle parent = handle()) { template <typename T> inline object cast(const T &value, return_value_policy policy = return_value_policy::automatic_reference, handle parent = handle()) {
if (policy == return_value_policy::automatic) if (policy == return_value_policy::automatic)
policy = std::is_pointer<T>::value ? return_value_policy::take_ownership : return_value_policy::copy; policy = std::is_pointer<T>::value ? return_value_policy::take_ownership : return_value_policy::copy;
else if (policy == return_value_policy::automatic_reference)
policy = std::is_pointer<T>::value ? return_value_policy::reference : return_value_policy::copy;
return object(detail::type_caster<typename detail::intrinsic_type<T>::type>::cast(value, policy, parent), false); return object(detail::type_caster<typename detail::intrinsic_type<T>::type>::cast(value, policy, parent), false);
} }
template <typename T> inline T handle::cast() const { return pybind11::cast<T>(*this); } template <typename T> inline T handle::cast() const { return pybind11::cast<T>(*this); }
template <> inline void handle::cast() const { return; } template <> inline void handle::cast() const { return; }
template <typename... Args> inline tuple make_tuple(Args&&... args_) { template <return_value_policy policy = return_value_policy::automatic_reference,
typename... Args> inline tuple make_tuple(Args&&... args_) {
const size_t size = sizeof...(Args); const size_t size = sizeof...(Args);
std::array<object, size> args { std::array<object, size> args {
{ object(detail::type_caster<typename detail::intrinsic_type<Args>::type>::cast( { object(detail::type_caster<typename detail::intrinsic_type<Args>::type>::cast(
std::forward<Args>(args_), return_value_policy::automatic, nullptr), false)... } std::forward<Args>(args_), policy, nullptr), false)... }
}; };
for (auto &arg_value : args) for (auto &arg_value : args)
if (!arg_value) if (!arg_value)
@ -732,7 +737,7 @@ template <typename... Args> inline tuple make_tuple(Args&&... args_) {
} }
template <typename... Args> inline object handle::call(Args&&... args) const { template <typename... Args> inline object handle::call(Args&&... args) const {
tuple args_tuple = make_tuple(std::forward<Args>(args)...); tuple args_tuple = pybind11::make_tuple(std::forward<Args>(args)...);
object result(PyObject_CallObject(m_ptr, args_tuple.ptr()), false); object result(PyObject_CallObject(m_ptr, args_tuple.ptr()), false);
if (!result) if (!result)
throw error_already_set(); throw error_already_set();

View File

@ -137,6 +137,9 @@ enum class return_value_policy : int {
/** Automatic: copy objects returned as values and take ownership of objects /** Automatic: copy objects returned as values and take ownership of objects
returned as pointers */ returned as pointers */
automatic = 0, automatic = 0,
/** Automatic variant 2: copy objects returned as values and reference objects
returned as pointers */
automatic_reference,
/** Reference the object and take ownership. Python will call the /** Reference the object and take ownership. Python will call the
destructor and delete operator when the reference count reaches zero */ destructor and delete operator when the reference count reaches zero */
take_ownership, take_ownership,