diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index 9c4b9680b..0b6ff0859 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -512,15 +512,17 @@ public: PYBIND11_TYPE_CASTER(T, _::value>("int", "float")); }; -template <> class type_caster { +template 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 : public void_caster {}; + template <> class type_caster : public type_caster { public: using type_caster::cast; diff --git a/include/pybind11/stl.h b/include/pybind11/stl.h index ae0b3affb..04d2daad1 100644 --- a/include/pybind11/stl.h +++ b/include/pybind11/stl.h @@ -205,7 +205,7 @@ template 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 struct type_caster> : public optional_caster> {}; + +template<> struct type_caster + : public void_caster {}; #endif #if PYBIND11_HAS_EXP_OPTIONAL template struct type_caster> : public optional_caster> {}; + +template<> struct type_caster + : public void_caster {}; #endif NAMESPACE_END(detail) diff --git a/tests/test_python_types.cpp b/tests/test_python_types.cpp index 6a9e3cf5c..8a58daf45 100644 --- a/tests/test_python_types.cpp +++ b/tests/test_python_types.cpp @@ -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); }); diff --git a/tests/test_python_types.py b/tests/test_python_types.py index 3a8a09ead..ff5018918 100644 --- a/tests/test_python_types.py +++ b/tests/test_python_types.py @@ -299,7 +299,7 @@ def test_accessors(): @pytest.mark.skipif(not has_optional, reason='no ') 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