mirror of
https://github.com/RYDE-WORK/pybind11.git
synced 2026-02-05 15:03:18 +08:00
Add type casters for nullopt_t, fix none refcount (#499)
* Incref returned None in std::optional type caster * Add type casters for nullopt_t * Add a test for nullopt_t
This commit is contained in:
parent
9a110e6da8
commit
425b4970b2
@ -512,15 +512,17 @@ public:
|
|||||||
PYBIND11_TYPE_CASTER(T, _<std::is_integral<T>::value>("int", "float"));
|
PYBIND11_TYPE_CASTER(T, _<std::is_integral<T>::value>("int", "float"));
|
||||||
};
|
};
|
||||||
|
|
||||||
template <> class type_caster<void_type> {
|
template<typename T> struct void_caster {
|
||||||
public:
|
public:
|
||||||
bool load(handle, bool) { return false; }
|
bool load(handle, bool) { return false; }
|
||||||
static handle cast(void_type, return_value_policy /* policy */, handle /* parent */) {
|
static handle cast(T, return_value_policy /* policy */, handle /* parent */) {
|
||||||
return none().inc_ref();
|
return none().inc_ref();
|
||||||
}
|
}
|
||||||
PYBIND11_TYPE_CASTER(void_type, _("None"));
|
PYBIND11_TYPE_CASTER(T, _("None"));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <> class type_caster<void_type> : public void_caster<void_type> {};
|
||||||
|
|
||||||
template <> class type_caster<void> : public type_caster<void_type> {
|
template <> class type_caster<void> : public type_caster<void_type> {
|
||||||
public:
|
public:
|
||||||
using type_caster<void_type>::cast;
|
using type_caster<void_type>::cast;
|
||||||
|
|||||||
@ -205,7 +205,7 @@ template<typename T> struct optional_caster {
|
|||||||
|
|
||||||
static handle cast(const T& src, return_value_policy policy, handle parent) {
|
static handle cast(const T& src, return_value_policy policy, handle parent) {
|
||||||
if (!src)
|
if (!src)
|
||||||
return none();
|
return none().inc_ref();
|
||||||
return caster_type::cast(*src, policy, parent);
|
return caster_type::cast(*src, policy, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,11 +232,17 @@ private:
|
|||||||
#if PYBIND11_HAS_OPTIONAL
|
#if PYBIND11_HAS_OPTIONAL
|
||||||
template<typename T> struct type_caster<std::optional<T>>
|
template<typename T> struct type_caster<std::optional<T>>
|
||||||
: public optional_caster<std::optional<T>> {};
|
: public optional_caster<std::optional<T>> {};
|
||||||
|
|
||||||
|
template<> struct type_caster<std::nullopt_t>
|
||||||
|
: public void_caster<std::nullopt_t> {};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if PYBIND11_HAS_EXP_OPTIONAL
|
#if PYBIND11_HAS_EXP_OPTIONAL
|
||||||
template<typename T> struct type_caster<std::experimental::optional<T>>
|
template<typename T> struct type_caster<std::experimental::optional<T>>
|
||||||
: public optional_caster<std::experimental::optional<T>> {};
|
: public optional_caster<std::experimental::optional<T>> {};
|
||||||
|
|
||||||
|
template<> struct type_caster<std::experimental::nullopt_t>
|
||||||
|
: public void_caster<std::experimental::nullopt_t> {};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
NAMESPACE_END(detail)
|
NAMESPACE_END(detail)
|
||||||
|
|||||||
@ -301,6 +301,9 @@ test_initializer python_types([](py::module &m) {
|
|||||||
m.def("half_or_none", [](int x) -> opt_int {
|
m.def("half_or_none", [](int x) -> opt_int {
|
||||||
return x ? opt_int(x / 2) : opt_int();
|
return x ? opt_int(x / 2) : opt_int();
|
||||||
});
|
});
|
||||||
|
m.def("test_nullopt", [](opt_int x) {
|
||||||
|
return x.value_or(42);
|
||||||
|
}, py::arg_v("x", std::experimental::nullopt, "None"));
|
||||||
#endif
|
#endif
|
||||||
m.attr("has_optional") = py::cast(has_optional);
|
m.attr("has_optional") = py::cast(has_optional);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -299,7 +299,7 @@ def test_accessors():
|
|||||||
|
|
||||||
@pytest.mark.skipif(not has_optional, reason='no <experimental/optional>')
|
@pytest.mark.skipif(not has_optional, reason='no <experimental/optional>')
|
||||||
def test_optional():
|
def test_optional():
|
||||||
from pybind11_tests import double_or_zero, half_or_none
|
from pybind11_tests import double_or_zero, half_or_none, test_nullopt
|
||||||
|
|
||||||
assert double_or_zero(None) == 0
|
assert double_or_zero(None) == 0
|
||||||
assert double_or_zero(42) == 84
|
assert double_or_zero(42) == 84
|
||||||
@ -308,3 +308,8 @@ def test_optional():
|
|||||||
assert half_or_none(0) is None
|
assert half_or_none(0) is None
|
||||||
assert half_or_none(42) == 21
|
assert half_or_none(42) == 21
|
||||||
pytest.raises(TypeError, half_or_none, 'foo')
|
pytest.raises(TypeError, half_or_none, 'foo')
|
||||||
|
|
||||||
|
assert test_nullopt() == 42
|
||||||
|
assert test_nullopt(None) == 42
|
||||||
|
assert test_nullopt(42) == 42
|
||||||
|
assert test_nullopt(43) == 43
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user