Skip to content

Commit

Permalink
Introduce reserve_if_available
Browse files Browse the repository at this point in the history
Summary:
This is useful when writing generic code that handles containers.  Some examples:
- std::unordered_map provides reserve(), but std::map does not
- std::vector provides reserve(), but std::deque and std::list do not

Reviewed By: yfeldblum

Differential Revision: D57718859

fbshipit-source-id: 9cb146b2950746e416c938b0cc6484715f58bb69
  • Loading branch information
marksantaniello authored and facebook-github-bot committed May 25, 2024
1 parent 2e2e7fe commit 945a193
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 0 deletions.
29 changes: 29 additions & 0 deletions folly/container/Reserve.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ using detect_bucket_count = decltype(FOLLY_DECLVAL(C).bucket_count());
template <typename C>
using detect_max_load_factor = decltype(FOLLY_DECLVAL(C).max_load_factor());

template <typename C, typename... A>
using detect_reserve = decltype(FOLLY_DECLVAL(C).reserve(FOLLY_DECLVAL(A)...));

template <typename C>
using container_detect_reserve =
detect_reserve<C, typename remove_cvref_t<C>::size_type>;

} // namespace detail

/**
Expand Down Expand Up @@ -78,4 +85,26 @@ struct grow_capacity_by_fn {

inline constexpr grow_capacity_by_fn grow_capacity_by{};

/**
* Useful when writing generic code that handles containers.
*
* Examples:
* - std::unordered_map provides reserve(), but std::map does not
* - std::vector provides reserve(), but std::deque and std::list do not
*/
struct reserve_if_available_fn {
template <typename C>
auto operator()(C& c, typename C::size_type const n) const
noexcept(!folly::is_detected_v<detail::container_detect_reserve, C&>) {
constexpr auto match =
folly::is_detected_v<detail::container_detect_reserve, C&>;
if constexpr (match) {
c.reserve(n);
}
return std::bool_constant<match>{};
}
};

inline constexpr reserve_if_available_fn reserve_if_available{};

} // namespace folly
14 changes: 14 additions & 0 deletions folly/container/test/ReserveTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#include <folly/container/Reserve.h>

#include <list>
#include <memory>
#include <unordered_map>
#include <vector>
Expand Down Expand Up @@ -157,3 +158,16 @@ TEST(ReserveUtil, F14NodeMapGrowBy) {
TEST(ReserveUtil, UnorderedMapGrowBy) {
testMapGrowBy<unordered_map>();
}

TEST(ReserveUtil, ReserveIfAvailableVector) {
std::vector<int> v;
auto r = folly::reserve_if_available(v, 42);
static_assert(std::is_same_v<decltype(r), std::true_type>);
EXPECT_GE(v.capacity(), 42);
}

TEST(ReserveUtil, ReserveIfAvailableList) {
std::list<int> l;
auto r = folly::reserve_if_available(l, 42);
static_assert(std::is_same_v<decltype(r), std::false_type>);
}

0 comments on commit 945a193

Please sign in to comment.