From 01f938e79938fd5b9bb6df2daeff95a625f6211f Mon Sep 17 00:00:00 2001 From: Boris Rasin Date: Mon, 8 Nov 2021 01:35:25 +0200 Subject: [PATCH] fix: add missing std::forward calls (#3443) * fix: add missing std::forward calls Two of the four cpp_function overloads are missing std::forward calls, which seems like a simple oversight. * add test for https://github.com/pybind/pybind11/pull/3443 * add py tests * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix test Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- include/pybind11/pybind11.h | 4 ++-- tests/test_methods_and_attributes.cpp | 15 +++++++++++++++ tests/test_methods_and_attributes.py | 8 ++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index 124ea37e5..b8b7c7a02 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -115,7 +115,7 @@ public: template // NOLINTNEXTLINE(google-explicit-constructor) cpp_function(Return (Class::*f)(Arg...)&, const Extra&... extra) { - initialize([f](Class *c, Arg... args) -> Return { return (c->*f)(args...); }, + initialize([f](Class *c, Arg... args) -> Return { return (c->*f)(std::forward(args)...); }, (Return (*) (Class *, Arg...)) nullptr, extra...); } @@ -133,7 +133,7 @@ public: template // NOLINTNEXTLINE(google-explicit-constructor) cpp_function(Return (Class::*f)(Arg...) const&, const Extra&... extra) { - initialize([f](const Class *c, Arg... args) -> Return { return (c->*f)(args...); }, + initialize([f](const Class *c, Arg... args) -> Return { return (c->*f)(std::forward(args)...); }, (Return (*)(const Class *, Arg ...)) nullptr, extra...); } diff --git a/tests/test_methods_and_attributes.cpp b/tests/test_methods_and_attributes.cpp index 2d303a44e..9e55452de 100644 --- a/tests/test_methods_and_attributes.cpp +++ b/tests/test_methods_and_attributes.cpp @@ -159,6 +159,14 @@ struct RefQualified { int constRefQualified(int other) const & { return value + other; } }; +// Test rvalue ref param +struct RValueRefParam { + std::size_t func1(std::string&& s) { return s.size(); } + std::size_t func2(std::string&& s) const { return s.size(); } + std::size_t func3(std::string&& s) & { return s.size(); } + std::size_t func4(std::string&& s) const & { return s.size(); } +}; + TEST_SUBMODULE(methods_and_attributes, m) { // test_methods_and_attributes py::class_ emna(m, "ExampleMandA"); @@ -409,4 +417,11 @@ TEST_SUBMODULE(methods_and_attributes, m) { .def_readonly("value", &RefQualified::value) .def("refQualified", &RefQualified::refQualified) .def("constRefQualified", &RefQualified::constRefQualified); + + py::class_(m, "RValueRefParam") + .def(py::init<>()) + .def("func1", &RValueRefParam::func1) + .def("func2", &RValueRefParam::func2) + .def("func3", &RValueRefParam::func3) + .def("func4", &RValueRefParam::func4); } diff --git a/tests/test_methods_and_attributes.py b/tests/test_methods_and_attributes.py index 866b3cea1..fa026f9ed 100644 --- a/tests/test_methods_and_attributes.py +++ b/tests/test_methods_and_attributes.py @@ -515,3 +515,11 @@ def test_overload_ordering(): assert "2. (arg0: {}) -> int".format(uni_name) in str(err.value) assert "3. (arg0: {}) -> int".format(uni_name) in str(err.value) assert "4. (arg0: int) -> int" in str(err.value) + + +def test_rvalue_ref_param(): + r = m.RValueRefParam() + assert r.func1("123") == 3 + assert r.func2("1234") == 4 + assert r.func3("12345") == 5 + assert r.func4("123456") == 6