diff options
author | 2022-04-18 08:12:19 -0700 | |
---|---|---|
committer | 2024-01-29 11:22:51 -0500 | |
commit | 70e4591214f3b5b7da4a8c0a17b71d7c69aa4aa1 (patch) | |
tree | 8c9d4480de1b596b2c934fff590cdd7926accde0 | |
parent | 1b685dd3b6373ba55be1c57c672a22533e16664d (diff) |
FTL: Fix SmallMap<K, V, 0>::try_emplace
SmallVector<T, N>::emplace_back returns a reference, whereas
SmallVector<T, 0>::emplace_back returns an iterator (because
its API must be compatible with StaticVector).
Bug: 185536303
Test: ftl_test
Change-Id: I6bdcd983c0bb2d2a326f79906997f85e89d7df44
-rw-r--r-- | include/ftl/small_map.h | 22 | ||||
-rw-r--r-- | libs/ftl/small_map_test.cpp | 55 |
2 files changed, 60 insertions, 17 deletions
diff --git a/include/ftl/small_map.h b/include/ftl/small_map.h index 49cde7fedc..83d5967464 100644 --- a/include/ftl/small_map.h +++ b/include/ftl/small_map.h @@ -107,12 +107,20 @@ class SmallMap final { template <typename Q, typename W, std::size_t M, typename E> SmallMap(SmallMap<Q, W, M, E> other) : map_(std::move(other.map_)) {} + static constexpr size_type static_capacity() { return N; } + size_type max_size() const { return map_.max_size(); } size_type size() const { return map_.size(); } bool empty() const { return map_.empty(); } // Returns whether the map is backed by static or dynamic storage. - bool dynamic() const { return map_.dynamic(); } + bool dynamic() const { + if constexpr (static_capacity() > 0) { + return map_.dynamic(); + } else { + return true; + } + } iterator begin() { return map_.begin(); } const_iterator begin() const { return cbegin(); } @@ -171,9 +179,15 @@ class SmallMap final { return {it, false}; } - auto& ref = map_.emplace_back(std::piecewise_construct, std::forward_as_tuple(key), - std::forward_as_tuple(std::forward<Args>(args)...)); - return {&ref, true}; + decltype(auto) ref_or_it = + map_.emplace_back(std::piecewise_construct, std::forward_as_tuple(key), + std::forward_as_tuple(std::forward<Args>(args)...)); + + if constexpr (static_capacity() > 0) { + return {&ref_or_it, true}; + } else { + return {ref_or_it, true}; + } } // Replaces a mapping if it exists, and returns an iterator to it. Returns the end() iterator diff --git a/libs/ftl/small_map_test.cpp b/libs/ftl/small_map_test.cpp index 634877f672..e96d70d8ad 100644 --- a/libs/ftl/small_map_test.cpp +++ b/libs/ftl/small_map_test.cpp @@ -189,9 +189,20 @@ TEST(SmallMap, Get) { } } -TEST(SmallMap, TryEmplace) { - SmallMap<int, std::string, 3> map; - using Pair = decltype(map)::value_type; +template <typename Capacity> +struct SmallMapTest : testing::Test { + static constexpr std::size_t kCapacity = Capacity{}(); +}; + +template <std::size_t N> +using Capacity = std::integral_constant<std::size_t, N>; + +using Capacities = testing::Types<Capacity<3>, Capacity<0>>; +TYPED_TEST_SUITE(SmallMapTest, Capacities, ); + +TYPED_TEST(SmallMapTest, TryEmplace) { + SmallMap<int, std::string, TestFixture::kCapacity> map; + using Pair = typename decltype(map)::value_type; { const auto [it, ok] = map.try_emplace(123, "abc"); @@ -207,14 +218,22 @@ TEST(SmallMap, TryEmplace) { const auto [it, ok] = map.try_emplace(-1); ASSERT_TRUE(ok); EXPECT_EQ(*it, Pair(-1, std::string())); - EXPECT_FALSE(map.dynamic()); + if constexpr (map.static_capacity() > 0) { + EXPECT_FALSE(map.dynamic()); + } else { + EXPECT_TRUE(map.dynamic()); + } } { // Insertion fails if mapping exists. const auto [it, ok] = map.try_emplace(42, "!!!"); EXPECT_FALSE(ok); EXPECT_EQ(*it, Pair(42, "???")); - EXPECT_FALSE(map.dynamic()); + if constexpr (map.static_capacity() > 0) { + EXPECT_FALSE(map.dynamic()); + } else { + EXPECT_TRUE(map.dynamic()); + } } { // Insertion at capacity promotes the map. @@ -240,9 +259,9 @@ struct String { } // namespace -TEST(SmallMap, TryReplace) { - SmallMap<int, String, 3> map = ftl::init::map(1, "a")(2, "B"); - using Pair = decltype(map)::value_type; +TYPED_TEST(SmallMapTest, TryReplace) { + SmallMap<int, String, TestFixture::kCapacity> map = ftl::init::map(1, "a")(2, "B"); + using Pair = typename decltype(map)::value_type; { // Replacing fails unless mapping exists. @@ -260,7 +279,12 @@ TEST(SmallMap, TryReplace) { EXPECT_EQ(*it, Pair(2, "b")); } - EXPECT_FALSE(map.dynamic()); + if constexpr (map.static_capacity() > 0) { + EXPECT_FALSE(map.dynamic()); + } else { + EXPECT_TRUE(map.dynamic()); + } + EXPECT_TRUE(map.try_emplace(3, "abc").second); EXPECT_TRUE(map.try_emplace(4, "d").second); EXPECT_TRUE(map.dynamic()); @@ -284,9 +308,9 @@ TEST(SmallMap, TryReplace) { EXPECT_EQ(map, SmallMap(ftl::init::map(4, "d"s)(3, "c"s)(2, "b"s)(1, "a"s))); } -TEST(SmallMap, EmplaceOrReplace) { - SmallMap<int, String, 3> map = ftl::init::map(1, "a")(2, "B"); - using Pair = decltype(map)::value_type; +TYPED_TEST(SmallMapTest, EmplaceOrReplace) { + SmallMap<int, String, TestFixture::kCapacity> map = ftl::init::map(1, "a")(2, "B"); + using Pair = typename decltype(map)::value_type; { // New mapping is emplaced. @@ -305,7 +329,12 @@ TEST(SmallMap, EmplaceOrReplace) { EXPECT_EQ(*it, Pair(2, "b")); } - EXPECT_FALSE(map.dynamic()); + if constexpr (map.static_capacity() > 0) { + EXPECT_FALSE(map.dynamic()); + } else { + EXPECT_TRUE(map.dynamic()); + } + EXPECT_FALSE(map.emplace_or_replace(3, "abc").second); // Replace. EXPECT_TRUE(map.emplace_or_replace(4, "d").second); // Emplace. EXPECT_TRUE(map.dynamic()); |