Skip to content

Commit 5aa0fad

Browse files
authored
perf: call reserve method in set and map casters (#4194)
* Call reserve method in set and map casters too * Refactor template logic into has_reserve_method * Adjust comment for reviews * Rearrange reserve_maybe to not be underneath macro
1 parent f743bdf commit 5aa0fad

File tree

1 file changed

+24
-3
lines changed

1 file changed

+24
-3
lines changed

include/pybind11/stl.h

+24-3
Original file line numberDiff line numberDiff line change
@@ -49,17 +49,31 @@ constexpr forwarded_type<T, U> forward_like(U &&u) {
4949
return std::forward<detail::forwarded_type<T, U>>(std::forward<U>(u));
5050
}
5151

52+
// Checks if a container has a STL style reserve method.
53+
// This will only return true for a `reserve()` with a `void` return.
54+
template <typename C>
55+
using has_reserve_method = std::is_same<decltype(std::declval<C>().reserve(0)), void>;
56+
5257
template <typename Type, typename Key>
5358
struct set_caster {
5459
using type = Type;
5560
using key_conv = make_caster<Key>;
5661

62+
private:
63+
template <typename T = Type, enable_if_t<has_reserve_method<T>::value, int> = 0>
64+
void reserve_maybe(const anyset &s, Type *) {
65+
value.reserve(s.size());
66+
}
67+
void reserve_maybe(const anyset &, void *) {}
68+
69+
public:
5770
bool load(handle src, bool convert) {
5871
if (!isinstance<anyset>(src)) {
5972
return false;
6073
}
6174
auto s = reinterpret_borrow<anyset>(src);
6275
value.clear();
76+
reserve_maybe(s, &value);
6377
for (auto entry : s) {
6478
key_conv conv;
6579
if (!conv.load(entry, convert)) {
@@ -94,12 +108,21 @@ struct map_caster {
94108
using key_conv = make_caster<Key>;
95109
using value_conv = make_caster<Value>;
96110

111+
private:
112+
template <typename T = Type, enable_if_t<has_reserve_method<T>::value, int> = 0>
113+
void reserve_maybe(const dict &d, Type *) {
114+
value.reserve(d.size());
115+
}
116+
void reserve_maybe(const dict &, void *) {}
117+
118+
public:
97119
bool load(handle src, bool convert) {
98120
if (!isinstance<dict>(src)) {
99121
return false;
100122
}
101123
auto d = reinterpret_borrow<dict>(src);
102124
value.clear();
125+
reserve_maybe(d, &value);
103126
for (auto it : d) {
104127
key_conv kconv;
105128
value_conv vconv;
@@ -160,9 +183,7 @@ struct list_caster {
160183
}
161184

162185
private:
163-
template <
164-
typename T = Type,
165-
enable_if_t<std::is_same<decltype(std::declval<T>().reserve(0)), void>::value, int> = 0>
186+
template <typename T = Type, enable_if_t<has_reserve_method<T>::value, int> = 0>
166187
void reserve_maybe(const sequence &s, Type *) {
167188
value.reserve(s.size());
168189
}

0 commit comments

Comments
 (0)