From 99579f58f638c7d09abe245d0b67263637bfa17c Mon Sep 17 00:00:00 2001 From: Aaron Gokaslan Date: Thu, 17 Jun 2021 19:58:44 -0400 Subject: [PATCH 1/3] Apply clang-tidy performance fixes --- .clang-tidy | 4 ++ include/pybind11/buffer_info.h | 6 +-- include/pybind11/cast.h | 10 ++-- .../detail/smart_holder_type_casters.h | 2 +- include/pybind11/eval.h | 8 +-- include/pybind11/iostream.h | 39 +++++++-------- include/pybind11/numpy.h | 4 +- include/pybind11/pybind11.h | 8 +-- include/pybind11/pytypes.h | 10 ++-- include/pybind11/stl.h | 11 +++-- include/pybind11/stl_bind.h | 49 ++++++++++--------- .../pybind11/trampoline_self_life_support.h | 2 +- 12 files changed, 82 insertions(+), 71 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index e29d929897..3079b3b3c0 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -10,4 +10,8 @@ modernize-use-auto, modernize-use-emplace, ' +CheckOptions: +- key: performance-unnecessary-value-param.AllowedTypes + value: 'exception_ptr$;' + HeaderFilterRegex: 'pybind11/.*h' diff --git a/include/pybind11/buffer_info.h b/include/pybind11/buffer_info.h index d803004a10..47dc39d4ea 100644 --- a/include/pybind11/buffer_info.h +++ b/include/pybind11/buffer_info.h @@ -91,11 +91,9 @@ struct buffer_info { buffer_info(const buffer_info &) = delete; buffer_info& operator=(const buffer_info &) = delete; - buffer_info(buffer_info &&other) { - (*this) = std::move(other); - } + buffer_info(buffer_info &&other) noexcept { (*this) = std::move(other); } - buffer_info& operator=(buffer_info &&rhs) { + buffer_info &operator=(buffer_info &&rhs) noexcept { ptr = rhs.ptr; itemsize = rhs.itemsize; size = rhs.size; diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index 1ff698f3b3..8e96749252 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -1091,7 +1091,9 @@ struct kw_only {}; struct pos_only {}; template -arg_v arg::operator=(T &&value) const { return {std::move(*this), std::forward(value)}; } +arg_v arg::operator=(T &&value) const { + return {*this, std::forward(value)}; +} /// Alias for backward compatibility -- to be removed in version 2.0 template using arg_t = arg_v; @@ -1313,7 +1315,7 @@ class unpacking_collector { "may be passed via py::arg() to a python function call. " "(compile in debug mode for details)"); } - [[noreturn]] static void nameless_argument_error(std::string type) { + [[noreturn]] static void nameless_argument_error(const std::string& type) { throw type_error("Got kwargs without a name of type '" + type + "'; only named " "arguments may be passed via py::arg() to a python function call. "); } @@ -1322,7 +1324,7 @@ class unpacking_collector { "(compile in debug mode for details)"); } - [[noreturn]] static void multiple_values_error(std::string name) { + [[noreturn]] static void multiple_values_error(const std::string& name) { throw type_error("Got multiple values for keyword argument '" + name + "'"); } @@ -1331,7 +1333,7 @@ class unpacking_collector { "(compile in debug mode for details)"); } - [[noreturn]] static void argument_cast_error(std::string name, std::string type) { + [[noreturn]] static void argument_cast_error(const std::string& name, const std::string& type) { throw cast_error("Unable to convert call argument '" + name + "' of type '" + type + "' to Python object"); } diff --git a/include/pybind11/detail/smart_holder_type_casters.h b/include/pybind11/detail/smart_holder_type_casters.h index 15ab81c58d..653332bf83 100644 --- a/include/pybind11/detail/smart_holder_type_casters.h +++ b/include/pybind11/detail/smart_holder_type_casters.h @@ -79,7 +79,7 @@ class modified_type_caster_generic_load_impl { } // type_caster_generic::load_value END } - loaded_v_h = std::move(v_h); + loaded_v_h = v_h; loaded_v_h.type = typeinfo; } diff --git a/include/pybind11/eval.h b/include/pybind11/eval.h index fa6b8af479..bf06504a33 100644 --- a/include/pybind11/eval.h +++ b/include/pybind11/eval.h @@ -11,6 +11,8 @@ #pragma once +#include + #include "pybind11.h" PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) @@ -43,7 +45,7 @@ enum eval_mode { }; template -object eval(str expr, object global = globals(), object local = object()) { +object eval(const str &expr, object global = globals(), object local = object()) { if (!local) local = global; @@ -75,8 +77,8 @@ object eval(const char (&s)[N], object global = globals(), object local = object return eval(expr, global, local); } -inline void exec(str expr, object global = globals(), object local = object()) { - eval(expr, global, local); +inline void exec(const str &expr, object global = globals(), object local = object()) { + eval(expr, std::move(global), std::move(local)); } template diff --git a/include/pybind11/iostream.h b/include/pybind11/iostream.h index 7c1c718b02..6a793eadca 100644 --- a/include/pybind11/iostream.h +++ b/include/pybind11/iostream.h @@ -11,14 +11,15 @@ #include "pybind11.h" -#include -#include -#include -#include -#include +#include #include +#include #include -#include +#include +#include +#include +#include +#include PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) PYBIND11_NAMESPACE_BEGIN(detail) @@ -117,11 +118,8 @@ class pythonbuf : public std::streambuf { } public: - - pythonbuf(object pyostream, size_t buffer_size = 1024) - : buf_size(buffer_size), - d_buffer(new char[buf_size]), - pywrite(pyostream.attr("write")), + pythonbuf(const object &pyostream, size_t buffer_size = 1024) + : buf_size(buffer_size), d_buffer(new char[buf_size]), pywrite(pyostream.attr("write")), pyflush(pyostream.attr("flush")) { setp(d_buffer.get(), d_buffer.get() + buf_size - 1); } @@ -168,9 +166,8 @@ class scoped_ostream_redirect { detail::pythonbuf buffer; public: - scoped_ostream_redirect( - std::ostream &costream = std::cout, - object pyostream = module_::import("sys").attr("stdout")) + scoped_ostream_redirect(std::ostream &costream = std::cout, + const object &pyostream = module_::import("sys").attr("stdout")) : costream(costream), buffer(pyostream) { old = costream.rdbuf(&buffer); } @@ -199,10 +196,9 @@ class scoped_ostream_redirect { \endrst */ class scoped_estream_redirect : public scoped_ostream_redirect { public: - scoped_estream_redirect( - std::ostream &costream = std::cerr, - object pyostream = module_::import("sys").attr("stderr")) - : scoped_ostream_redirect(costream,pyostream) {} + scoped_estream_redirect(std::ostream &costream = std::cerr, + const object &pyostream = module_::import("sys").attr("stderr")) + : scoped_ostream_redirect(costream, pyostream) {} }; @@ -261,9 +257,10 @@ PYBIND11_NAMESPACE_END(detail) m.noisy_function_with_error_printing() \endrst */ -inline class_ add_ostream_redirect(module_ m, std::string name = "ostream_redirect") { - return class_(m, name.c_str(), module_local()) - .def(init(), arg("stdout")=true, arg("stderr")=true) +inline class_ +add_ostream_redirect(module_ m, const std::string &name = "ostream_redirect") { + return class_(std::move(m), name.c_str(), module_local()) + .def(init(), arg("stdout") = true, arg("stderr") = true) .def("__enter__", &detail::OstreamRedirect::enter) .def("__exit__", [](detail::OstreamRedirect &self_, args) { self_.exit(); }); } diff --git a/include/pybind11/numpy.h b/include/pybind11/numpy.h index ec4c53b430..eb2bfca768 100644 --- a/include/pybind11/numpy.h +++ b/include/pybind11/numpy.h @@ -164,10 +164,10 @@ struct npy_api { NPY_ULONG_, NPY_ULONGLONG_, NPY_UINT_), }; - typedef struct { + using PyArray_Dims = struct { Py_intptr_t *ptr; int len; - } PyArray_Dims; + }; static npy_api& get() { static npy_api api = lookup(); diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index a1379e16c5..eb22e09254 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -1472,15 +1472,15 @@ class class_ : public detail::generic_type { template class_ &def_readwrite_static(const char *name, D *pm, const Extra& ...extra) { - cpp_function fget([pm](object) -> const D &{ return *pm; }, scope(*this)), - fset([pm](object, const D &value) { *pm = value; }, scope(*this)); + cpp_function fget([pm](const object&) -> const D &{ return *pm; }, scope(*this)), + fset([pm](const object&, const D &value) { *pm = value; }, scope(*this)); def_property_static(name, fget, fset, return_value_policy::reference, extra...); return *this; } template class_ &def_readonly_static(const char *name, const D *pm, const Extra& ...extra) { - cpp_function fget([pm](object) -> const D &{ return *pm; }, scope(*this)); + cpp_function fget([pm](const object&) -> const D &{ return *pm; }, scope(*this)); def_property_readonly_static(name, fget, return_value_policy::reference, extra...); return *this; } @@ -2140,7 +2140,7 @@ exception ®ister_exception(handle scope, } PYBIND11_NAMESPACE_BEGIN(detail) -PYBIND11_NOINLINE inline void print(tuple args, dict kwargs) { +PYBIND11_NOINLINE inline void print(const tuple& args, const dict& kwargs) { auto strings = tuple(args.size()); for (size_t i = 0; i < args.size(); ++i) { strings[i] = str(args[i]); diff --git a/include/pybind11/pytypes.h b/include/pybind11/pytypes.h index 6a1d8356a5..06a48124f8 100644 --- a/include/pybind11/pytypes.h +++ b/include/pybind11/pytypes.h @@ -503,7 +503,7 @@ class accessor : public object_api> { public: accessor(handle obj, key_type key) : obj(obj), key(std::move(key)) { } accessor(const accessor &) = default; - accessor(accessor &&) = default; + accessor(accessor &&) noexcept = default; // accessor overload required to override default assignment operator (templates are not allowed // to replace default compiler-generated assignments). @@ -1507,8 +1507,12 @@ class memoryview : public object { const void *ptr, ssize_t itemsize, const char *format, detail::any_container shape, detail::any_container strides) { - return memoryview::from_buffer( - const_cast(ptr), itemsize, format, shape, strides, true); + return memoryview::from_buffer(const_cast(ptr), + itemsize, + format, + std::move(std::move(shape)), + std::move(std::move(strides)), + true); } template diff --git a/include/pybind11/stl.h b/include/pybind11/stl.h index 18fbafb1e2..61d3fba61e 100644 --- a/include/pybind11/stl.h +++ b/include/pybind11/stl.h @@ -159,10 +159,13 @@ template struct list_caster { } private: - template ().reserve(0)), void>::value, int> = 0> - void reserve_maybe(sequence s, Type *) { value.reserve(s.size()); } - void reserve_maybe(sequence, void *) { } + template < + typename T = Type, + enable_if_t().reserve(0)), void>::value, int> = 0> + void reserve_maybe(const sequence &s, Type *) { + value.reserve(s.size()); + } + void reserve_maybe(const sequence &, void *) {} public: template diff --git a/include/pybind11/stl_bind.h b/include/pybind11/stl_bind.h index 39499f3491..fb0104e8c6 100644 --- a/include/pybind11/stl_bind.h +++ b/include/pybind11/stl_bind.h @@ -128,11 +128,11 @@ void vector_modifiers(enable_if_t(new Vector()); v->reserve(len_hint(it)); for (handle h : it) - v->push_back(h.cast()); + v->push_back(h.cast()); return v.release(); })); @@ -151,27 +151,28 @@ void vector_modifiers(enable_if_t()); - } - } catch (const cast_error &) { - v.erase(v.begin() + static_cast(old_size), v.end()); - try { - v.shrink_to_fit(); - } catch (const std::exception &) { - // Do nothing - } - throw; - } - }, - arg("L"), - "Extend the list by appending all the items in the given list" - ); + cl.def( + "extend", + [](Vector &v, const iterable &it) { + const size_t old_size = v.size(); + v.reserve(old_size + len_hint(it)); + try { + for (handle h : it) { + v.push_back(h.cast()); + } + } catch (const cast_error &) { + v.erase(v.begin() + static_cast(old_size), + v.end()); + try { + v.shrink_to_fit(); + } catch (const std::exception &) { + // Do nothing + } + throw; + } + }, + arg("L"), + "Extend the list by appending all the items in the given list"); cl.def("insert", [](Vector &v, DiffType i, const T &x) { @@ -400,7 +401,7 @@ void vector_buffer_impl(Class_& cl, std::true_type) { return buffer_info(v.data(), static_cast(sizeof(T)), format_descriptor::format(), 1, {v.size()}, {sizeof(T)}); }); - cl.def(init([](buffer buf) { + cl.def(init([](const buffer &buf) { auto info = buf.request(); if (info.ndim != 1 || info.strides[0] % static_cast(sizeof(T))) throw type_error("Only valid 1D buffers can be copied to a vector"); diff --git a/include/pybind11/trampoline_self_life_support.h b/include/pybind11/trampoline_self_life_support.h index 115f094ba7..cdb1fb3ed3 100644 --- a/include/pybind11/trampoline_self_life_support.h +++ b/include/pybind11/trampoline_self_life_support.h @@ -53,7 +53,7 @@ struct trampoline_self_life_support { // For the next two, the default implementations generate undefined behavior (ASAN failures // manually verified). The reason is that v_h needs to be kept default-initialized. trampoline_self_life_support(const trampoline_self_life_support &) {} - trampoline_self_life_support(trampoline_self_life_support &&) {} + trampoline_self_life_support(trampoline_self_life_support &&) noexcept {} // These should never be needed (please provide test cases if you think they are). trampoline_self_life_support &operator=(const trampoline_self_life_support &) = delete; From 077f344acb7368fb8495d7a86b4cdd3e841d443c Mon Sep 17 00:00:00 2001 From: Aaron Gokaslan Date: Thu, 17 Jun 2021 20:37:02 -0400 Subject: [PATCH 2/3] Fix bug introduced by double insert --- include/pybind11/pytypes.h | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/include/pybind11/pytypes.h b/include/pybind11/pytypes.h index 06a48124f8..d1d92af6ad 100644 --- a/include/pybind11/pytypes.h +++ b/include/pybind11/pytypes.h @@ -1507,12 +1507,8 @@ class memoryview : public object { const void *ptr, ssize_t itemsize, const char *format, detail::any_container shape, detail::any_container strides) { - return memoryview::from_buffer(const_cast(ptr), - itemsize, - format, - std::move(std::move(shape)), - std::move(std::move(strides)), - true); + return memoryview::from_buffer( + const_cast(ptr), itemsize, format, std::move(shape), std::move(strides), true); } template From d094e6e69324cd3a23559978c350af3118d629de Mon Sep 17 00:00:00 2001 From: Aaron Gokaslan Date: Fri, 18 Jun 2021 15:12:14 -0400 Subject: [PATCH 3/3] Revert all non-smart-holder changes --- .clang-tidy | 4 --- include/pybind11/buffer_info.h | 6 +++-- include/pybind11/cast.h | 10 +++---- include/pybind11/eval.h | 8 +++--- include/pybind11/iostream.h | 39 ++++++++++++++------------- include/pybind11/numpy.h | 4 +-- include/pybind11/pybind11.h | 8 +++--- include/pybind11/pytypes.h | 4 +-- include/pybind11/stl.h | 11 +++----- include/pybind11/stl_bind.h | 49 +++++++++++++++++----------------- 10 files changed, 68 insertions(+), 75 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index 3079b3b3c0..e29d929897 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -10,8 +10,4 @@ modernize-use-auto, modernize-use-emplace, ' -CheckOptions: -- key: performance-unnecessary-value-param.AllowedTypes - value: 'exception_ptr$;' - HeaderFilterRegex: 'pybind11/.*h' diff --git a/include/pybind11/buffer_info.h b/include/pybind11/buffer_info.h index 47dc39d4ea..d803004a10 100644 --- a/include/pybind11/buffer_info.h +++ b/include/pybind11/buffer_info.h @@ -91,9 +91,11 @@ struct buffer_info { buffer_info(const buffer_info &) = delete; buffer_info& operator=(const buffer_info &) = delete; - buffer_info(buffer_info &&other) noexcept { (*this) = std::move(other); } + buffer_info(buffer_info &&other) { + (*this) = std::move(other); + } - buffer_info &operator=(buffer_info &&rhs) noexcept { + buffer_info& operator=(buffer_info &&rhs) { ptr = rhs.ptr; itemsize = rhs.itemsize; size = rhs.size; diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index 8e96749252..1ff698f3b3 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -1091,9 +1091,7 @@ struct kw_only {}; struct pos_only {}; template -arg_v arg::operator=(T &&value) const { - return {*this, std::forward(value)}; -} +arg_v arg::operator=(T &&value) const { return {std::move(*this), std::forward(value)}; } /// Alias for backward compatibility -- to be removed in version 2.0 template using arg_t = arg_v; @@ -1315,7 +1313,7 @@ class unpacking_collector { "may be passed via py::arg() to a python function call. " "(compile in debug mode for details)"); } - [[noreturn]] static void nameless_argument_error(const std::string& type) { + [[noreturn]] static void nameless_argument_error(std::string type) { throw type_error("Got kwargs without a name of type '" + type + "'; only named " "arguments may be passed via py::arg() to a python function call. "); } @@ -1324,7 +1322,7 @@ class unpacking_collector { "(compile in debug mode for details)"); } - [[noreturn]] static void multiple_values_error(const std::string& name) { + [[noreturn]] static void multiple_values_error(std::string name) { throw type_error("Got multiple values for keyword argument '" + name + "'"); } @@ -1333,7 +1331,7 @@ class unpacking_collector { "(compile in debug mode for details)"); } - [[noreturn]] static void argument_cast_error(const std::string& name, const std::string& type) { + [[noreturn]] static void argument_cast_error(std::string name, std::string type) { throw cast_error("Unable to convert call argument '" + name + "' of type '" + type + "' to Python object"); } diff --git a/include/pybind11/eval.h b/include/pybind11/eval.h index bf06504a33..fa6b8af479 100644 --- a/include/pybind11/eval.h +++ b/include/pybind11/eval.h @@ -11,8 +11,6 @@ #pragma once -#include - #include "pybind11.h" PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) @@ -45,7 +43,7 @@ enum eval_mode { }; template -object eval(const str &expr, object global = globals(), object local = object()) { +object eval(str expr, object global = globals(), object local = object()) { if (!local) local = global; @@ -77,8 +75,8 @@ object eval(const char (&s)[N], object global = globals(), object local = object return eval(expr, global, local); } -inline void exec(const str &expr, object global = globals(), object local = object()) { - eval(expr, std::move(global), std::move(local)); +inline void exec(str expr, object global = globals(), object local = object()) { + eval(expr, global, local); } template diff --git a/include/pybind11/iostream.h b/include/pybind11/iostream.h index 6a793eadca..7c1c718b02 100644 --- a/include/pybind11/iostream.h +++ b/include/pybind11/iostream.h @@ -11,15 +11,14 @@ #include "pybind11.h" -#include -#include -#include -#include -#include -#include #include +#include #include -#include +#include +#include +#include +#include +#include PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) PYBIND11_NAMESPACE_BEGIN(detail) @@ -118,8 +117,11 @@ class pythonbuf : public std::streambuf { } public: - pythonbuf(const object &pyostream, size_t buffer_size = 1024) - : buf_size(buffer_size), d_buffer(new char[buf_size]), pywrite(pyostream.attr("write")), + + pythonbuf(object pyostream, size_t buffer_size = 1024) + : buf_size(buffer_size), + d_buffer(new char[buf_size]), + pywrite(pyostream.attr("write")), pyflush(pyostream.attr("flush")) { setp(d_buffer.get(), d_buffer.get() + buf_size - 1); } @@ -166,8 +168,9 @@ class scoped_ostream_redirect { detail::pythonbuf buffer; public: - scoped_ostream_redirect(std::ostream &costream = std::cout, - const object &pyostream = module_::import("sys").attr("stdout")) + scoped_ostream_redirect( + std::ostream &costream = std::cout, + object pyostream = module_::import("sys").attr("stdout")) : costream(costream), buffer(pyostream) { old = costream.rdbuf(&buffer); } @@ -196,9 +199,10 @@ class scoped_ostream_redirect { \endrst */ class scoped_estream_redirect : public scoped_ostream_redirect { public: - scoped_estream_redirect(std::ostream &costream = std::cerr, - const object &pyostream = module_::import("sys").attr("stderr")) - : scoped_ostream_redirect(costream, pyostream) {} + scoped_estream_redirect( + std::ostream &costream = std::cerr, + object pyostream = module_::import("sys").attr("stderr")) + : scoped_ostream_redirect(costream,pyostream) {} }; @@ -257,10 +261,9 @@ PYBIND11_NAMESPACE_END(detail) m.noisy_function_with_error_printing() \endrst */ -inline class_ -add_ostream_redirect(module_ m, const std::string &name = "ostream_redirect") { - return class_(std::move(m), name.c_str(), module_local()) - .def(init(), arg("stdout") = true, arg("stderr") = true) +inline class_ add_ostream_redirect(module_ m, std::string name = "ostream_redirect") { + return class_(m, name.c_str(), module_local()) + .def(init(), arg("stdout")=true, arg("stderr")=true) .def("__enter__", &detail::OstreamRedirect::enter) .def("__exit__", [](detail::OstreamRedirect &self_, args) { self_.exit(); }); } diff --git a/include/pybind11/numpy.h b/include/pybind11/numpy.h index eb2bfca768..ec4c53b430 100644 --- a/include/pybind11/numpy.h +++ b/include/pybind11/numpy.h @@ -164,10 +164,10 @@ struct npy_api { NPY_ULONG_, NPY_ULONGLONG_, NPY_UINT_), }; - using PyArray_Dims = struct { + typedef struct { Py_intptr_t *ptr; int len; - }; + } PyArray_Dims; static npy_api& get() { static npy_api api = lookup(); diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index eb22e09254..a1379e16c5 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -1472,15 +1472,15 @@ class class_ : public detail::generic_type { template class_ &def_readwrite_static(const char *name, D *pm, const Extra& ...extra) { - cpp_function fget([pm](const object&) -> const D &{ return *pm; }, scope(*this)), - fset([pm](const object&, const D &value) { *pm = value; }, scope(*this)); + cpp_function fget([pm](object) -> const D &{ return *pm; }, scope(*this)), + fset([pm](object, const D &value) { *pm = value; }, scope(*this)); def_property_static(name, fget, fset, return_value_policy::reference, extra...); return *this; } template class_ &def_readonly_static(const char *name, const D *pm, const Extra& ...extra) { - cpp_function fget([pm](const object&) -> const D &{ return *pm; }, scope(*this)); + cpp_function fget([pm](object) -> const D &{ return *pm; }, scope(*this)); def_property_readonly_static(name, fget, return_value_policy::reference, extra...); return *this; } @@ -2140,7 +2140,7 @@ exception ®ister_exception(handle scope, } PYBIND11_NAMESPACE_BEGIN(detail) -PYBIND11_NOINLINE inline void print(const tuple& args, const dict& kwargs) { +PYBIND11_NOINLINE inline void print(tuple args, dict kwargs) { auto strings = tuple(args.size()); for (size_t i = 0; i < args.size(); ++i) { strings[i] = str(args[i]); diff --git a/include/pybind11/pytypes.h b/include/pybind11/pytypes.h index d1d92af6ad..6a1d8356a5 100644 --- a/include/pybind11/pytypes.h +++ b/include/pybind11/pytypes.h @@ -503,7 +503,7 @@ class accessor : public object_api> { public: accessor(handle obj, key_type key) : obj(obj), key(std::move(key)) { } accessor(const accessor &) = default; - accessor(accessor &&) noexcept = default; + accessor(accessor &&) = default; // accessor overload required to override default assignment operator (templates are not allowed // to replace default compiler-generated assignments). @@ -1508,7 +1508,7 @@ class memoryview : public object { detail::any_container shape, detail::any_container strides) { return memoryview::from_buffer( - const_cast(ptr), itemsize, format, std::move(shape), std::move(strides), true); + const_cast(ptr), itemsize, format, shape, strides, true); } template diff --git a/include/pybind11/stl.h b/include/pybind11/stl.h index 61d3fba61e..18fbafb1e2 100644 --- a/include/pybind11/stl.h +++ b/include/pybind11/stl.h @@ -159,13 +159,10 @@ template struct list_caster { } private: - template < - typename T = Type, - enable_if_t().reserve(0)), void>::value, int> = 0> - void reserve_maybe(const sequence &s, Type *) { - value.reserve(s.size()); - } - void reserve_maybe(const sequence &, void *) {} + template ().reserve(0)), void>::value, int> = 0> + void reserve_maybe(sequence s, Type *) { value.reserve(s.size()); } + void reserve_maybe(sequence, void *) { } public: template diff --git a/include/pybind11/stl_bind.h b/include/pybind11/stl_bind.h index fb0104e8c6..39499f3491 100644 --- a/include/pybind11/stl_bind.h +++ b/include/pybind11/stl_bind.h @@ -128,11 +128,11 @@ void vector_modifiers(enable_if_t(new Vector()); v->reserve(len_hint(it)); for (handle h : it) - v->push_back(h.cast()); + v->push_back(h.cast()); return v.release(); })); @@ -151,28 +151,27 @@ void vector_modifiers(enable_if_t()); - } - } catch (const cast_error &) { - v.erase(v.begin() + static_cast(old_size), - v.end()); - try { - v.shrink_to_fit(); - } catch (const std::exception &) { - // Do nothing - } - throw; - } - }, - arg("L"), - "Extend the list by appending all the items in the given list"); + cl.def("extend", + [](Vector &v, iterable it) { + const size_t old_size = v.size(); + v.reserve(old_size + len_hint(it)); + try { + for (handle h : it) { + v.push_back(h.cast()); + } + } catch (const cast_error &) { + v.erase(v.begin() + static_cast(old_size), v.end()); + try { + v.shrink_to_fit(); + } catch (const std::exception &) { + // Do nothing + } + throw; + } + }, + arg("L"), + "Extend the list by appending all the items in the given list" + ); cl.def("insert", [](Vector &v, DiffType i, const T &x) { @@ -401,7 +400,7 @@ void vector_buffer_impl(Class_& cl, std::true_type) { return buffer_info(v.data(), static_cast(sizeof(T)), format_descriptor::format(), 1, {v.size()}, {sizeof(T)}); }); - cl.def(init([](const buffer &buf) { + cl.def(init([](buffer buf) { auto info = buf.request(); if (info.ndim != 1 || info.strides[0] % static_cast(sizeof(T))) throw type_error("Only valid 1D buffers can be copied to a vector");