Skip to content

Commit 01f938e

Browse files
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 #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>
1 parent a61e354 commit 01f938e

File tree

3 files changed

+25
-2
lines changed

3 files changed

+25
-2
lines changed

include/pybind11/pybind11.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ class cpp_function : public function {
115115
template <typename Return, typename Class, typename... Arg, typename... Extra>
116116
// NOLINTNEXTLINE(google-explicit-constructor)
117117
cpp_function(Return (Class::*f)(Arg...)&, const Extra&... extra) {
118-
initialize([f](Class *c, Arg... args) -> Return { return (c->*f)(args...); },
118+
initialize([f](Class *c, Arg... args) -> Return { return (c->*f)(std::forward<Arg>(args)...); },
119119
(Return (*) (Class *, Arg...)) nullptr, extra...);
120120
}
121121

@@ -133,7 +133,7 @@ class cpp_function : public function {
133133
template <typename Return, typename Class, typename... Arg, typename... Extra>
134134
// NOLINTNEXTLINE(google-explicit-constructor)
135135
cpp_function(Return (Class::*f)(Arg...) const&, const Extra&... extra) {
136-
initialize([f](const Class *c, Arg... args) -> Return { return (c->*f)(args...); },
136+
initialize([f](const Class *c, Arg... args) -> Return { return (c->*f)(std::forward<Arg>(args)...); },
137137
(Return (*)(const Class *, Arg ...)) nullptr, extra...);
138138
}
139139

tests/test_methods_and_attributes.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,14 @@ struct RefQualified {
159159
int constRefQualified(int other) const & { return value + other; }
160160
};
161161

162+
// Test rvalue ref param
163+
struct RValueRefParam {
164+
std::size_t func1(std::string&& s) { return s.size(); }
165+
std::size_t func2(std::string&& s) const { return s.size(); }
166+
std::size_t func3(std::string&& s) & { return s.size(); }
167+
std::size_t func4(std::string&& s) const & { return s.size(); }
168+
};
169+
162170
TEST_SUBMODULE(methods_and_attributes, m) {
163171
// test_methods_and_attributes
164172
py::class_<ExampleMandA> emna(m, "ExampleMandA");
@@ -409,4 +417,11 @@ TEST_SUBMODULE(methods_and_attributes, m) {
409417
.def_readonly("value", &RefQualified::value)
410418
.def("refQualified", &RefQualified::refQualified)
411419
.def("constRefQualified", &RefQualified::constRefQualified);
420+
421+
py::class_<RValueRefParam>(m, "RValueRefParam")
422+
.def(py::init<>())
423+
.def("func1", &RValueRefParam::func1)
424+
.def("func2", &RValueRefParam::func2)
425+
.def("func3", &RValueRefParam::func3)
426+
.def("func4", &RValueRefParam::func4);
412427
}

tests/test_methods_and_attributes.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,3 +515,11 @@ def test_overload_ordering():
515515
assert "2. (arg0: {}) -> int".format(uni_name) in str(err.value)
516516
assert "3. (arg0: {}) -> int".format(uni_name) in str(err.value)
517517
assert "4. (arg0: int) -> int" in str(err.value)
518+
519+
520+
def test_rvalue_ref_param():
521+
r = m.RValueRefParam()
522+
assert r.func1("123") == 3
523+
assert r.func2("1234") == 4
524+
assert r.func3("12345") == 5
525+
assert r.func4("123456") == 6

0 commit comments

Comments
 (0)