From b22ee64c7309eb7344031b5e5385e6907d84c7eb Mon Sep 17 00:00:00 2001 From: Laramie Leavitt Date: Mon, 21 Mar 2022 22:58:04 -0700 Subject: [PATCH] Add type_caster (#3818) * Add type_caster for std::variant Add type_caster, allowing std::variant * Add variant test methods * Add std::monostate tests * Update test_stl.py Remove erroneous extra tests * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update test fn name * And update the doc() test Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- include/pybind11/stl.h | 3 +++ tests/test_stl.cpp | 20 ++++++++++++++++++-- tests/test_stl.py | 16 ++++++++++++++++ 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/include/pybind11/stl.h b/include/pybind11/stl.h index e3a061444..3d1ca7ac2 100644 --- a/include/pybind11/stl.h +++ b/include/pybind11/stl.h @@ -406,6 +406,9 @@ struct variant_caster> { #if defined(PYBIND11_HAS_VARIANT) template struct type_caster> : variant_caster> {}; + +template <> +struct type_caster : public void_caster {}; #endif PYBIND11_NAMESPACE_END(detail) diff --git a/tests/test_stl.cpp b/tests/test_stl.cpp index fd1824beb..b56a91953 100644 --- a/tests/test_stl.cpp +++ b/tests/test_stl.cpp @@ -37,9 +37,10 @@ struct type_caster : void_caster {}; // Test with `std::variant` in C++17 mode, or with `boost::variant` in C++11/14 #if defined(PYBIND11_HAS_VARIANT) using std::variant; +# define PYBIND11_TEST_VARIANT 1 #elif defined(PYBIND11_TEST_BOOST) # include -# define PYBIND11_HAS_VARIANT 1 +# define PYBIND11_TEST_VARIANT 1 using boost::variant; namespace pybind11 { @@ -424,7 +425,7 @@ TEST_SUBMODULE(stl, m) { m.def("parent_path", [](const std::filesystem::path &p) { return p.parent_path(); }); #endif -#ifdef PYBIND11_HAS_VARIANT +#ifdef PYBIND11_TEST_VARIANT static_assert(std::is_same::value, "visitor::result_type is required by boost::variant in C++11 mode"); @@ -435,6 +436,9 @@ TEST_SUBMODULE(stl, m) { result_type operator()(const std::string &) { return "std::string"; } result_type operator()(double) { return "double"; } result_type operator()(std::nullptr_t) { return "std::nullptr_t"; } +# if defined(PYBIND11_HAS_VARIANT) + result_type operator()(std::monostate) { return "std::monostate"; } +# endif }; // test_variant @@ -448,6 +452,18 @@ TEST_SUBMODULE(stl, m) { using V = variant; return py::make_tuple(V(5), V("Hello")); }); + +# if defined(PYBIND11_HAS_VARIANT) + // std::monostate tests. + m.def("load_monostate_variant", + [](const variant &v) -> const char * { + return py::detail::visit_helper::call(visitor(), v); + }); + m.def("cast_monostate_variant", []() { + using V = variant; + return py::make_tuple(V{}, V(5), V("Hello")); + }); +# endif #endif // #528: templated constructor diff --git a/tests/test_stl.py b/tests/test_stl.py index a3d686689..3dc55230a 100644 --- a/tests/test_stl.py +++ b/tests/test_stl.py @@ -263,6 +263,22 @@ def test_variant(doc): ) +@pytest.mark.skipif( + not hasattr(m, "load_monostate_variant"), reason="no std::monostate" +) +def test_variant_monostate(doc): + assert m.load_monostate_variant(None) == "std::monostate" + assert m.load_monostate_variant(1) == "int" + assert m.load_monostate_variant("1") == "std::string" + + assert m.cast_monostate_variant() == (None, 5, "Hello") + + assert ( + doc(m.load_monostate_variant) + == "load_monostate_variant(arg0: Union[None, int, str]) -> str" + ) + + def test_vec_of_reference_wrapper(): """#171: Can't return reference wrappers (or STL structures containing them)""" assert (