Skip to content

Commit

Permalink
perf: call reserve method in set and map casters (#4194)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
Skylion007 authored Sep 25, 2022
1 parent f743bdf commit 5aa0fad
Showing 1 changed file with 24 additions and 3 deletions.
27 changes: 24 additions & 3 deletions include/pybind11/stl.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,31 @@ constexpr forwarded_type<T, U> forward_like(U &&u) {
return std::forward<detail::forwarded_type<T, U>>(std::forward<U>(u));
}

// Checks if a container has a STL style reserve method.
// This will only return true for a `reserve()` with a `void` return.
template <typename C>
using has_reserve_method = std::is_same<decltype(std::declval<C>().reserve(0)), void>;

template <typename Type, typename Key>
struct set_caster {
using type = Type;
using key_conv = make_caster<Key>;

private:
template <typename T = Type, enable_if_t<has_reserve_method<T>::value, int> = 0>
void reserve_maybe(const anyset &s, Type *) {
value.reserve(s.size());
}
void reserve_maybe(const anyset &, void *) {}

public:
bool load(handle src, bool convert) {
if (!isinstance<anyset>(src)) {
return false;
}
auto s = reinterpret_borrow<anyset>(src);
value.clear();
reserve_maybe(s, &value);
for (auto entry : s) {
key_conv conv;
if (!conv.load(entry, convert)) {
Expand Down Expand Up @@ -94,12 +108,21 @@ struct map_caster {
using key_conv = make_caster<Key>;
using value_conv = make_caster<Value>;

private:
template <typename T = Type, enable_if_t<has_reserve_method<T>::value, int> = 0>
void reserve_maybe(const dict &d, Type *) {
value.reserve(d.size());
}
void reserve_maybe(const dict &, void *) {}

public:
bool load(handle src, bool convert) {
if (!isinstance<dict>(src)) {
return false;
}
auto d = reinterpret_borrow<dict>(src);
value.clear();
reserve_maybe(d, &value);
for (auto it : d) {
key_conv kconv;
value_conv vconv;
Expand Down Expand Up @@ -160,9 +183,7 @@ struct list_caster {
}

private:
template <
typename T = Type,
enable_if_t<std::is_same<decltype(std::declval<T>().reserve(0)), void>::value, int> = 0>
template <typename T = Type, enable_if_t<has_reserve_method<T>::value, int> = 0>
void reserve_maybe(const sequence &s, Type *) {
value.reserve(s.size());
}
Expand Down

0 comments on commit 5aa0fad

Please sign in to comment.