From 827e167038d1444880114d0738561d2b5ce7c45b Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Thu, 4 May 2023 16:47:45 -0700 Subject: [PATCH 01/13] Reproducer for `error: call to implicitly-deleted default constructor` triggered by stl.h `array_caster`: ``` clang++ -o pybind11/tests/test_stl_no_default_ctor.os -c -std=c++17 -fPIC -fvisibility=hidden -O0 -g -Wall -Wextra -Wconversion -Wcast-qual -Wdeprecated -Wundef -Wnon-virtual-dtor -Wunused-result -Werror -isystem /usr/include/python3.10 -isystem /usr/include/eigen3 -DPYBIND11_STRICT_ASSERTS_CLASS_HOLDER_VS_TYPE_CASTER_MIX -DPYBIND11_ENABLE_TYPE_CASTER_ODR_GUARD_IF_AVAILABLE -DPYBIND11_TEST_BOOST -Ipybind11/include -I/usr/local/google/home/rwgk/forked/pybind11/include -I/usr/local/google/home/rwgk/clone/pybind11/include /usr/local/google/home/rwgk/forked/pybind11/tests/test_stl_no_default_ctor.cpp In file included from /usr/local/google/home/rwgk/forked/pybind11/tests/test_stl_no_default_ctor.cpp:1: In file included from /usr/local/google/home/rwgk/forked/pybind11/include/pybind11/stl.h:12: In file included from /usr/local/google/home/rwgk/forked/pybind11/include/pybind11/pybind11.h:13: In file included from /usr/local/google/home/rwgk/forked/pybind11/include/pybind11/detail/class.h:12: In file included from /usr/local/google/home/rwgk/forked/pybind11/include/pybind11/attr.h:14: In file included from /usr/local/google/home/rwgk/forked/pybind11/include/pybind11/cast.h:18: /usr/local/google/home/rwgk/forked/pybind11/include/pybind11/detail/type_caster_odr_guard.h:111:5: error: call to implicitly-deleted default constructor of 'pybind11::detail::type_caster>' type_caster_odr_guard() { ^ /usr/bin/../lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/tuple:190:9: note: in instantiation of member function 'pybind11::detail::type_caster_odr_guard, pybind11::detail::type_caster>>::type_caster_odr_guard' requested here : _M_head_impl() { } ^ /usr/local/google/home/rwgk/forked/pybind11/include/pybind11/pybind11.h:104:9: note: in instantiation of function template specialization 'pybind11::cpp_function::initialize<(lambda at /usr/local/google/home/rwgk/forked/pybind11/include/pybind11/pybind11.h:1583:29), void, pybind11_tests::stl_no_default_ctor::NodeArray &, const std::array &, pybind11::is_method>' requested here initialize( ^ /usr/local/google/home/rwgk/forked/pybind11/include/pybind11/pybind11.h:1583:16: note: in instantiation of function template specialization 'pybind11::cpp_function::cpp_function<(lambda at /usr/local/google/home/rwgk/forked/pybind11/include/pybind11/pybind11.h:1583:29), pybind11::is_method, void>' requested here return cpp_function([pm](T &c, const D &value) { c.*pm = value; }, is_method(hdl)); ^ /usr/local/google/home/rwgk/forked/pybind11/include/pybind11/pybind11.h:1926:54: note: in instantiation of function template specialization 'pybind11::property_cpp_function>::write pybind11_tests::stl_no_default_ctor::NodeArray::*, 0>' requested here property_cpp_function::write(pm, *this), ^ /usr/local/google/home/rwgk/forked/pybind11/tests/test_stl_no_default_ctor.cpp:32:10: note: in instantiation of function template specialization 'pybind11::class_::def_readwrite>' requested here .def_readwrite("arr", &NodeArray::arr); ^ /usr/local/google/home/rwgk/forked/pybind11/include/pybind11/stl.h:288:7: note: default constructor of 'type_caster>' is implicitly deleted because base class 'array_caster, pybind11_tests::stl_no_default_ctor::Node, false, 2UL>' has a deleted default constructor : array_caster, Type, false, Size> {}; ^ /usr/local/google/home/rwgk/forked/pybind11/include/pybind11/stl.h:278:5: note: default constructor of 'array_caster, pybind11_tests::stl_no_default_ctor::Node, false, 2>' is implicitly deleted because field 'value' has a deleted default constructor PYBIND11_TYPE_CASTER_RVPP(ArrayType, ^ /usr/local/google/home/rwgk/forked/pybind11/include/pybind11/cast.h:262:5: note: expanded from macro 'PYBIND11_TYPE_CASTER_RVPP' PYBIND11_TYPE_CASTER_IMPL(type, py_name, ::pybind11::return_value_policy_pack) ^ /usr/local/google/home/rwgk/forked/pybind11/include/pybind11/cast.h:232:10: note: expanded from macro 'PYBIND11_TYPE_CASTER_IMPL' type value; \ ^ /usr/bin/../lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/array:115:56: note: default constructor of 'array' is implicitly deleted because field '_M_elems' has no default constructor typename _AT_Type::_Type _M_elems; ^ 1 error generated. ``` --- tests/CMakeLists.txt | 1 + tests/test_stl_no_default_ctor.cpp | 33 ++++++++++++++++++++++++++++++ tests/test_stl_no_default_ctor.py | 8 ++++++++ 3 files changed, 42 insertions(+) create mode 100644 tests/test_stl_no_default_ctor.cpp create mode 100644 tests/test_stl_no_default_ctor.py diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 097c8d3b..e1462bc0 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -176,6 +176,7 @@ set(PYBIND11_TEST_FILES test_smart_ptr test_stl test_stl_binders + test_stl_no_default_ctor test_tagbased_polymorphic test_thread test_type_caster_odr_guard_1 diff --git a/tests/test_stl_no_default_ctor.cpp b/tests/test_stl_no_default_ctor.cpp new file mode 100644 index 00000000..b7c16f2a --- /dev/null +++ b/tests/test_stl_no_default_ctor.cpp @@ -0,0 +1,33 @@ +#include + +#include "pybind11_tests.h" + +#include + +namespace pybind11_tests { +namespace stl_no_default_ctor { + +struct Node { + constexpr Node() {} // COMMENT OUT TO REPRODUCE PROBLEM. + explicit constexpr Node(int val) : val{val} {} + + int val = -88; +}; + +struct NodeArray { + explicit constexpr NodeArray(int i) : arr{Node(10 + i), Node(20 + i)} {} + + std::array arr; +}; + +} // namespace stl_no_default_ctor +} // namespace pybind11_tests + +using namespace pybind11_tests::stl_no_default_ctor; + +TEST_SUBMODULE(stl_no_default_ctor, m) { + py::class_(m, "Node").def_readonly("val", &Node::val); + py::class_(m, "NodeArray") + .def(py::init()) + .def_readwrite("arr", &NodeArray::arr); +} diff --git a/tests/test_stl_no_default_ctor.py b/tests/test_stl_no_default_ctor.py new file mode 100644 index 00000000..849c4016 --- /dev/null +++ b/tests/test_stl_no_default_ctor.py @@ -0,0 +1,8 @@ +from pybind11_tests import stl_no_default_ctor as m + + +def test_readwrite_arr(): + obj = m.NodeArray(3) + assert [e.val for e in obj.arr] == [13, 23] + obj.arr = m.NodeArray(4).arr + assert [e.val for e in obj.arr] == [14, 24] From cca21eeebcc0958227da37439a9eba6ec1e8ed2f Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 9 Jan 2024 17:42:14 -0800 Subject: [PATCH 02/13] Expand `PYBIND11_TYPE_CASTER_RVPP` macro. --- include/pybind11/stl.h | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/include/pybind11/stl.h b/include/pybind11/stl.h index 0a5aa9cf..2a078d4e 100644 --- a/include/pybind11/stl.h +++ b/include/pybind11/stl.h @@ -420,13 +420,35 @@ struct array_caster { return l.release(); } - PYBIND11_TYPE_CASTER_RVPP(ArrayType, - const_name(const_name(""), const_name("Annotated[")) - + const_name("list[") + value_conv::name + const_name("]") - + const_name(const_name(""), - const_name(", FixedSize(") - + const_name() - + const_name(")]"))); +protected: + ArrayType value; + +public: + static constexpr auto name + = const_name(const_name(""), const_name("Annotated[")) + const_name("list[") + + value_conv::name + const_name("]") + + const_name( + const_name(""), const_name(", FixedSize(") + const_name() + const_name(")]")); + + template >::value, int> = 0> + static handle cast(T_ *src, const return_value_policy_pack &policy, handle parent) { + if (!src) { + return none().release(); + } + if (policy == return_value_policy::take_ownership) { + auto h = cast(std::move(*src), policy, parent); + delete src; + return h; + } + return cast(*src, policy, parent); + } + + operator ArrayType *() { return &value; } + operator ArrayType &() { return value; } + operator ArrayType &&() && { return std::move(value); } + + template + using cast_op_type = movable_cast_op_type; }; template From 3d618953a375f9c7ef8136a483426fa1659d5c9b Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 9 Jan 2024 21:03:34 -0800 Subject: [PATCH 03/13] Resolve clang-tidy and clang <= 5 errors. --- include/pybind11/stl.h | 3 +++ tests/test_stl_no_default_ctor.cpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/include/pybind11/stl.h b/include/pybind11/stl.h index 2a078d4e..795559f1 100644 --- a/include/pybind11/stl.h +++ b/include/pybind11/stl.h @@ -443,8 +443,11 @@ struct array_caster { return cast(*src, policy, parent); } + // NOLINTNEXTLINE(google-explicit-constructor) operator ArrayType *() { return &value; } + // NOLINTNEXTLINE(google-explicit-constructor) operator ArrayType &() { return value; } + // NOLINTNEXTLINE(google-explicit-constructor) operator ArrayType &&() && { return std::move(value); } template diff --git a/tests/test_stl_no_default_ctor.cpp b/tests/test_stl_no_default_ctor.cpp index b7c16f2a..052ca0e0 100644 --- a/tests/test_stl_no_default_ctor.cpp +++ b/tests/test_stl_no_default_ctor.cpp @@ -15,7 +15,7 @@ struct Node { }; struct NodeArray { - explicit constexpr NodeArray(int i) : arr{Node(10 + i), Node(20 + i)} {} + explicit constexpr NodeArray(int i) : arr({Node(10 + i), Node(20 + i)}) {} std::array arr; }; From aa82e3a645289ba5bee662f84583445f9317dfa4 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 9 Jan 2024 21:24:03 -0800 Subject: [PATCH 04/13] Second try: Resolve clang-tidy and clang <= 5 errors. --- tests/test_stl_no_default_ctor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_stl_no_default_ctor.cpp b/tests/test_stl_no_default_ctor.cpp index 052ca0e0..71dd9658 100644 --- a/tests/test_stl_no_default_ctor.cpp +++ b/tests/test_stl_no_default_ctor.cpp @@ -8,14 +8,14 @@ namespace pybind11_tests { namespace stl_no_default_ctor { struct Node { - constexpr Node() {} // COMMENT OUT TO REPRODUCE PROBLEM. + constexpr Node() = default; // COMMENT OUT TO REPRODUCE PROBLEM. explicit constexpr Node(int val) : val{val} {} int val = -88; }; struct NodeArray { - explicit constexpr NodeArray(int i) : arr({Node(10 + i), Node(20 + i)}) {} + explicit constexpr NodeArray(int i) : arr{{Node(10 + i), Node(20 + i)}} {} std::array arr; }; From e26769acb1ab510a8ec1ff008bf7af5592a8bd2e Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Thu, 11 Jan 2024 16:21:33 -0800 Subject: [PATCH 05/13] First working version of `array_caster` that works for types without a default constructor. --- include/pybind11/stl.h | 48 +++++++++++++++++++++++------- tests/test_stl_no_default_ctor.cpp | 1 - 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/include/pybind11/stl.h b/include/pybind11/stl.h index 795559f1..1b3e61ca 100644 --- a/include/pybind11/stl.h +++ b/include/pybind11/stl.h @@ -352,36 +352,64 @@ struct type_caster> : list_caster struct type_caster> : list_caster, Type> {}; +template +ArrayType vector_to_array_impl(V &&v, index_sequence) { + return {{std::move(v[I])...}}; +} + +// Based on https://en.cppreference.com/w/cpp/container/array/to_array +template +ArrayType vector_to_array(V &&v) { + return vector_to_array_impl(std::forward(v), make_index_sequence{}); +} + template struct array_caster { using value_conv = make_caster; private: template - bool require_size(enable_if_t size) { - if (value.size() != size) { - value.resize(size); - } + bool require_size(enable_if_t) { return true; } + template bool require_size(enable_if_t size) { return size == Size; } + using temp_space_type = std::vector; + + template + void move_temp_to_value(enable_if_t temp) { + value.reset(new ArrayType{}); + value->resize(temp.size()); + size_t ctr = 0; + for (auto elem : temp) { + (*value)[ctr++] = std::move(elem); + } + } + + template + void move_temp_to_value(enable_if_t temp) { + value.reset(new ArrayType{vector_to_array(std::move(temp))}); + } + bool convert_elements(handle seq, bool convert) { auto l = reinterpret_borrow(seq); if (!require_size(l.size())) { return false; } - size_t ctr = 0; + temp_space_type temp; + temp.reserve(l.size()); for (auto it : l) { value_conv conv; if (!conv.load(it, convert)) { return false; } - value[ctr++] = cast_op(std::move(conv)); + temp.emplace_back(cast_op(std::move(conv))); } + move_temp_to_value(std::move(temp)); return true; } @@ -421,7 +449,7 @@ struct array_caster { } protected: - ArrayType value; + std::unique_ptr value; public: static constexpr auto name @@ -444,11 +472,11 @@ struct array_caster { } // NOLINTNEXTLINE(google-explicit-constructor) - operator ArrayType *() { return &value; } + operator ArrayType *() { return &(*value); } // NOLINTNEXTLINE(google-explicit-constructor) - operator ArrayType &() { return value; } + operator ArrayType &() { return *value; } // NOLINTNEXTLINE(google-explicit-constructor) - operator ArrayType &&() && { return std::move(value); } + operator ArrayType &&() && { return std::move(*value); } template using cast_op_type = movable_cast_op_type; diff --git a/tests/test_stl_no_default_ctor.cpp b/tests/test_stl_no_default_ctor.cpp index 71dd9658..a24a9f6b 100644 --- a/tests/test_stl_no_default_ctor.cpp +++ b/tests/test_stl_no_default_ctor.cpp @@ -8,7 +8,6 @@ namespace pybind11_tests { namespace stl_no_default_ctor { struct Node { - constexpr Node() = default; // COMMENT OUT TO REPRODUCE PROBLEM. explicit constexpr Node(int val) : val{val} {} int val = -88; From 080fa2b6fbb6ba2793d9772a01f364b43b972928 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Thu, 11 Jan 2024 23:03:38 -0800 Subject: [PATCH 06/13] Try `()` instead of `{}` to see if that resolves clang 3.6 and gcc 4.8.5 compilation errors. --- include/pybind11/stl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/pybind11/stl.h b/include/pybind11/stl.h index 1b3e61ca..a57ad8bc 100644 --- a/include/pybind11/stl.h +++ b/include/pybind11/stl.h @@ -392,7 +392,7 @@ struct array_caster { template void move_temp_to_value(enable_if_t temp) { - value.reset(new ArrayType{vector_to_array(std::move(temp))}); + value.reset(new ArrayType(vector_to_array(std::move(temp)))); } bool convert_elements(handle seq, bool convert) { From 6dd0c70ab30915d592c95d4fdf98c80f6de2b68c Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Fri, 12 Jan 2024 08:40:24 -0800 Subject: [PATCH 07/13] Add minor comment. --- include/pybind11/stl.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/pybind11/stl.h b/include/pybind11/stl.h index a57ad8bc..a5822e42 100644 --- a/include/pybind11/stl.h +++ b/include/pybind11/stl.h @@ -458,6 +458,7 @@ struct array_caster { + const_name( const_name(""), const_name(", FixedSize(") + const_name() + const_name(")]")); + // Code copied from PYBIND11_TYPE_CASTER macro. template >::value, int> = 0> static handle cast(T_ *src, const return_value_policy_pack &policy, handle parent) { if (!src) { @@ -465,7 +466,7 @@ struct array_caster { } if (policy == return_value_policy::take_ownership) { auto h = cast(std::move(*src), policy, parent); - delete src; + delete src; // WARNING: Assumes `src` was allocated with `new`. return h; } return cast(*src, policy, parent); From cb0021cf8a333f0cca0766ae68bacbb521a870f4 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Fri, 12 Jan 2024 09:09:48 -0800 Subject: [PATCH 08/13] Avoid `temp` storage if `Resizable` is `true`. --- include/pybind11/stl.h | 48 ++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/include/pybind11/stl.h b/include/pybind11/stl.h index a5822e42..06bb288b 100644 --- a/include/pybind11/stl.h +++ b/include/pybind11/stl.h @@ -368,39 +368,37 @@ struct array_caster { using value_conv = make_caster; private: - template - bool require_size(enable_if_t) { - return true; - } - - template - bool require_size(enable_if_t size) { - return size == Size; - } - - using temp_space_type = std::vector; - - template - void move_temp_to_value(enable_if_t temp) { + template = 0> + bool convert_elements(handle seq, bool convert) { + auto l = reinterpret_borrow(seq); value.reset(new ArrayType{}); - value->resize(temp.size()); + // For the resize to work, `Value` must be default constructible. + // For `std::valarray`, this is a requirement: + // https://en.cppreference.com/w/cpp/named_req/NumericType + value->resize(l.size()); size_t ctr = 0; - for (auto elem : temp) { - (*value)[ctr++] = std::move(elem); + for (auto it : l) { + value_conv conv; + if (!conv.load(it, convert)) { + return false; + } + (*value)[ctr++] = cast_op(std::move(conv)); } + return true; } - template - void move_temp_to_value(enable_if_t temp) { - value.reset(new ArrayType(vector_to_array(std::move(temp)))); - } - + template = 0> bool convert_elements(handle seq, bool convert) { auto l = reinterpret_borrow(seq); - if (!require_size(l.size())) { + if (l.size() != Size) { return false; } - temp_space_type temp; + // The `temp` storage is needed to support `Value` types that are not + // default-constructible. + // Deliberate choice: no template specializations, for simplicity, and + // because the compile time overhead for the specializations is deemed + // more significant than the runtime overhead for the `temp` storage. + std::vector temp; temp.reserve(l.size()); for (auto it : l) { value_conv conv; @@ -409,7 +407,7 @@ struct array_caster { } temp.emplace_back(cast_op(std::move(conv))); } - move_temp_to_value(std::move(temp)); + value.reset(new ArrayType(vector_to_array(std::move(temp)))); return true; } From d2e1222c5d53e5a3f92cea3e04ad4ba577bc2294 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Fri, 12 Jan 2024 09:21:36 -0800 Subject: [PATCH 09/13] Merge test_stl_no_default_ctor into test_stl --- tests/CMakeLists.txt | 1 - tests/test_stl.cpp | 17 ++++++++++++++++ tests/test_stl.py | 7 +++++++ tests/test_stl_no_default_ctor.cpp | 32 ------------------------------ tests/test_stl_no_default_ctor.py | 8 -------- 5 files changed, 24 insertions(+), 41 deletions(-) delete mode 100644 tests/test_stl_no_default_ctor.cpp delete mode 100644 tests/test_stl_no_default_ctor.py diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 55a94eb5..c55b0f2f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -175,7 +175,6 @@ set(PYBIND11_TEST_FILES test_smart_ptr test_stl test_stl_binders - test_stl_no_default_ctor test_tagbased_polymorphic test_thread test_type_caster_odr_guard_1 diff --git a/tests/test_stl.cpp b/tests/test_stl.cpp index 901ab8f7..cb2ecee6 100644 --- a/tests/test_stl.cpp +++ b/tests/test_stl.cpp @@ -201,6 +201,23 @@ TEST_SUBMODULE(stl, m) { m.def("cast_array", []() { return std::array{{1, 2}}; }); m.def("load_array", [](const std::array &a) { return a[0] == 1 && a[1] == 2; }); + struct NoDefaultCtor { + explicit constexpr NoDefaultCtor(int val) : val{val} {} + int val = -88; + }; + + struct NoDefaultCtorArray { + explicit constexpr NoDefaultCtorArray(int i) + : arr{{NoDefaultCtor(10 + i), NoDefaultCtor(20 + i)}} {} + std::array arr; + }; + + // test_array_no_default_ctor + py::class_(m, "NoDefaultCtor").def_readonly("val", &NoDefaultCtor::val); + py::class_(m, "NoDefaultCtorArray") + .def(py::init()) + .def_readwrite("arr", &NoDefaultCtorArray::arr); + // test_valarray m.def("cast_valarray", []() { return std::valarray{1, 4, 9}; }); m.def("load_valarray", [](const std::valarray &v) { diff --git a/tests/test_stl.py b/tests/test_stl.py index 328cc85d..0c1c0a8a 100644 --- a/tests/test_stl.py +++ b/tests/test_stl.py @@ -46,6 +46,13 @@ def test_array(doc): ) +def test_array_no_default_ctor(): + lst = m.NoDefaultCtorArray(3) + assert [e.val for e in lst.arr] == [13, 23] + lst.arr = m.NoDefaultCtorArray(4).arr + assert [e.val for e in lst.arr] == [14, 24] + + def test_valarray(doc): """std::valarray <-> list""" lst = m.cast_valarray() diff --git a/tests/test_stl_no_default_ctor.cpp b/tests/test_stl_no_default_ctor.cpp deleted file mode 100644 index a24a9f6b..00000000 --- a/tests/test_stl_no_default_ctor.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include - -#include "pybind11_tests.h" - -#include - -namespace pybind11_tests { -namespace stl_no_default_ctor { - -struct Node { - explicit constexpr Node(int val) : val{val} {} - - int val = -88; -}; - -struct NodeArray { - explicit constexpr NodeArray(int i) : arr{{Node(10 + i), Node(20 + i)}} {} - - std::array arr; -}; - -} // namespace stl_no_default_ctor -} // namespace pybind11_tests - -using namespace pybind11_tests::stl_no_default_ctor; - -TEST_SUBMODULE(stl_no_default_ctor, m) { - py::class_(m, "Node").def_readonly("val", &Node::val); - py::class_(m, "NodeArray") - .def(py::init()) - .def_readwrite("arr", &NodeArray::arr); -} diff --git a/tests/test_stl_no_default_ctor.py b/tests/test_stl_no_default_ctor.py deleted file mode 100644 index 849c4016..00000000 --- a/tests/test_stl_no_default_ctor.py +++ /dev/null @@ -1,8 +0,0 @@ -from pybind11_tests import stl_no_default_ctor as m - - -def test_readwrite_arr(): - obj = m.NodeArray(3) - assert [e.val for e in obj.arr] == [13, 23] - obj.arr = m.NodeArray(4).arr - assert [e.val for e in obj.arr] == [14, 24] From 3f14ae34a0fcf76676bd3fdb45669da18d3e5195 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Fri, 12 Jan 2024 09:42:40 -0800 Subject: [PATCH 10/13] Minor move of code blocks (no functional change). --- include/pybind11/stl.h | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/include/pybind11/stl.h b/include/pybind11/stl.h index 06bb288b..8424004b 100644 --- a/include/pybind11/stl.h +++ b/include/pybind11/stl.h @@ -368,6 +368,8 @@ struct array_caster { using value_conv = make_caster; private: + std::unique_ptr value; + template = 0> bool convert_elements(handle seq, bool convert) { auto l = reinterpret_borrow(seq); @@ -446,16 +448,6 @@ struct array_caster { return l.release(); } -protected: - std::unique_ptr value; - -public: - static constexpr auto name - = const_name(const_name(""), const_name("Annotated[")) + const_name("list[") - + value_conv::name + const_name("]") - + const_name( - const_name(""), const_name(", FixedSize(") + const_name() + const_name(")]")); - // Code copied from PYBIND11_TYPE_CASTER macro. template >::value, int> = 0> static handle cast(T_ *src, const return_value_policy_pack &policy, handle parent) { @@ -479,6 +471,12 @@ struct array_caster { template using cast_op_type = movable_cast_op_type; + + static constexpr auto name + = const_name(const_name(""), const_name("Annotated[")) + const_name("list[") + + value_conv::name + const_name("]") + + const_name( + const_name(""), const_name(", FixedSize(") + const_name() + const_name(")]")); }; template From 64dcab7fc21dcccbe3c15492e52e328128762a9e Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Fri, 12 Jan 2024 10:38:15 -0800 Subject: [PATCH 11/13] Remove unused default value. --- tests/test_stl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_stl.cpp b/tests/test_stl.cpp index cb2ecee6..c5cda933 100644 --- a/tests/test_stl.cpp +++ b/tests/test_stl.cpp @@ -203,7 +203,7 @@ TEST_SUBMODULE(stl, m) { struct NoDefaultCtor { explicit constexpr NoDefaultCtor(int val) : val{val} {} - int val = -88; + int val; }; struct NoDefaultCtorArray { From f90342a305a75b24cc2908cb4ee79da7babd9e3f Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 15 Jan 2024 15:28:21 -0800 Subject: [PATCH 12/13] IncludeCleaner (IWYU) fixes --- include/pybind11/stl.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/pybind11/stl.h b/include/pybind11/stl.h index 8424004b..b38b39b7 100644 --- a/include/pybind11/stl.h +++ b/include/pybind11/stl.h @@ -11,11 +11,14 @@ #include "pybind11.h" #include "detail/common.h" +#include "detail/descr.h" +#include "detail/type_caster_base.h" #include #include #include #include +#include #include #include #include From 8486c9eecf7e842c1a5c5395dcd4efe74d6bb769 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 16 Jan 2024 11:18:23 -0800 Subject: [PATCH 13/13] Add two comments: preserving existing behavior --- include/pybind11/stl.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/pybind11/stl.h b/include/pybind11/stl.h index b38b39b7..6212063b 100644 --- a/include/pybind11/stl.h +++ b/include/pybind11/stl.h @@ -377,7 +377,8 @@ struct array_caster { bool convert_elements(handle seq, bool convert) { auto l = reinterpret_borrow(seq); value.reset(new ArrayType{}); - // For the resize to work, `Value` must be default constructible. + // Using `resize` to preserve the behavior exactly as it was before google/pywrapcc#30034 + // For the `resize` to work, `Value` must be default constructible. // For `std::valarray`, this is a requirement: // https://en.cppreference.com/w/cpp/named_req/NumericType value->resize(l.size()); @@ -452,6 +453,7 @@ struct array_caster { } // Code copied from PYBIND11_TYPE_CASTER macro. + // Intentionally preserving the behavior exactly as it was before google/pywrapcc#30034 template >::value, int> = 0> static handle cast(T_ *src, const return_value_policy_pack &policy, handle parent) { if (!src) {