From 67a0cc4eed34a164628fe0f7380ed70abd4b9a54 Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Thu, 6 Jul 2017 20:41:52 -0400 Subject: [PATCH] Fix regression: container pointers not castable PR #936 broke the ability to return a pointer to a stl container (and, likewise, to a tuple) because the added deduced type matched a non-const pointer argument: the pointer-accepting `cast` in PYBIND11_TYPE_CASTER had a `const type *`, which is a worse match for a non-const pointer than the universal reference template #936 added. This changes the provided TYPE_CASTER cast(ptr) to take the pointer by template arg (so that it will accept either const or non-const pointer). It has two other effects: it slightly reduces .so size (because many type casters never actually need the pointer cast at all), and it allows type casters to provide their untemplated pointer `cast()` that will take precedence over the templated version provided in the macro. --- include/pybind11/cast.h | 5 +++-- tests/test_stl.cpp | 4 +++- tests/test_stl.py | 3 +++ 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index 27d5622c..33dc9f38 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -892,14 +892,15 @@ public: type value; \ public: \ static PYBIND11_DESCR name() { return type_descr(py_name); } \ - static handle cast(const type *src, return_value_policy policy, handle parent) { \ + template >::value, int> = 0> \ + static handle cast(T_ *src, return_value_policy policy, handle parent) { \ if (!src) return none().release(); \ return cast(*src, policy, parent); \ } \ operator type*() { return &value; } \ operator type&() { return value; } \ operator type&&() && { return std::move(value); } \ - template using cast_op_type = pybind11::detail::movable_cast_op_type<_T> + template using cast_op_type = pybind11::detail::movable_cast_op_type template using is_std_char_type = any_of< diff --git a/tests/test_stl.cpp b/tests/test_stl.cpp index 839c1af0..6ba9cb94 100644 --- a/tests/test_stl.cpp +++ b/tests/test_stl.cpp @@ -38,6 +38,9 @@ TEST_SUBMODULE(stl, m) { // test_vector m.def("cast_vector", []() { return std::vector{1}; }); m.def("load_vector", [](const std::vector &v) { return v.at(0) == 1 && v.at(1) == 2; }); + // Unnumbered regression (caused by #936): pointers to stl containers aren't castable + static std::vector lvv{2}; + m.def("cast_ptr_vector", []() { return &lvv; }); // test_array m.def("cast_array", []() { return std::array {{1 , 2}}; }); @@ -78,7 +81,6 @@ TEST_SUBMODULE(stl, m) { v.back()[1].back().emplace("a", RValueCaster{}); return v; }); - static std::vector lvv{2}; static std::array lva; static std::unordered_map lvm{{"a", RValueCaster{}}, {"b", RValueCaster{}}}; static std::unordered_map>>> lvn; diff --git a/tests/test_stl.py b/tests/test_stl.py index 0f019821..c2fa7db1 100644 --- a/tests/test_stl.py +++ b/tests/test_stl.py @@ -15,6 +15,9 @@ def test_vector(doc): assert doc(m.cast_vector) == "cast_vector() -> List[int]" assert doc(m.load_vector) == "load_vector(arg0: List[int]) -> bool" + # Test regression caused by 936: pointers to stl containers weren't castable + assert m.cast_ptr_vector() == ["lvalue", "lvalue"] + def test_array(doc): """std::array <-> list"""