mirror of
https://github.com/pybind/pybind11.git
synced 2025-01-19 01:15:52 +00: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"));
|
||||
};
|
||||
|
||||
template <> class type_caster<void_type> {
|
||||
template<typename T> struct void_caster {
|
||||
public:
|
||||
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();
|
||||
}
|
||||
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> {
|
||||
public:
|
||||
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) {
|
||||
if (!src)
|
||||
return none();
|
||||
return none().inc_ref();
|
||||
return caster_type::cast(*src, policy, parent);
|
||||
}
|
||||
|
||||
@ -232,11 +232,17 @@ private:
|
||||
#if PYBIND11_HAS_OPTIONAL
|
||||
template<typename T> struct type_caster<std::optional<T>>
|
||||
: public optional_caster<std::optional<T>> {};
|
||||
|
||||
template<> struct type_caster<std::nullopt_t>
|
||||
: public void_caster<std::nullopt_t> {};
|
||||
#endif
|
||||
|
||||
#if PYBIND11_HAS_EXP_OPTIONAL
|
||||
template<typename T> struct type_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
|
||||
|
||||
NAMESPACE_END(detail)
|
||||
|
@ -301,6 +301,9 @@ test_initializer python_types([](py::module &m) {
|
||||
m.def("half_or_none", [](int x) -> 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
|
||||
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>')
|
||||
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(42) == 84
|
||||
@ -308,3 +308,8 @@ def test_optional():
|
||||
assert half_or_none(0) is None
|
||||
assert half_or_none(42) == 21
|
||||
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…
Reference in New Issue
Block a user