From 12244d01218f5ca032b61cd8f779a7fe91b40bf3 Mon Sep 17 00:00:00 2001 From: Yedidya Feldblum Date: Thu, 21 Apr 2016 23:14:27 -0700 Subject: [PATCH] get_default and get_ref_default variants taking functions Summary:[Folly] `get_default` and `get_ref_default` variants taking functions. Useful if the default value is computationally expensive to construct or requires IO. Reviewed By: andriigrynenko, spacedentist Differential Revision: D3189247 fb-gh-sync-id: 51c64293f8712d7590348d53cbfd892a5efd9e82 fbshipit-source-id: 51c64293f8712d7590348d53cbfd892a5efd9e82 --- folly/MapUtil.h | 35 +++++++++++++++++++++++++++++++++++ folly/test/MapUtilTest.cpp | 21 +++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/folly/MapUtil.h b/folly/MapUtil.h index 0df5d788..f042bd2d 100644 --- a/folly/MapUtil.h +++ b/folly/MapUtil.h @@ -34,6 +34,22 @@ typename Map::mapped_type get_default( return (pos != map.end() ? pos->second : dflt); } +/** + * Give a map and a key, return the value corresponding to the key in the map, + * or a given default value if the key doesn't exist in the map. + */ +template < + class Map, + typename Func, + typename = typename std::enable_if::type, + typename Map::mapped_type>::value>::type> +typename Map::mapped_type +get_default(const Map& map, const typename Map::key_type& key, Func&& dflt) { + auto pos = map.find(key); + return pos != map.end() ? pos->second : dflt(); +} + /** * Given a map and a key, return the value corresponding to the key in the map, * or throw an exception of the specified type. @@ -77,6 +93,25 @@ const typename Map::mapped_type& get_ref_default( return (pos != map.end() ? pos->second : dflt); } +/** + * Given a map and a key, return a reference to the value corresponding to the + * key in the map, or the given default reference if the key doesn't exist in + * the map. + */ +template < + class Map, + typename Func, + typename = typename std::enable_if::type, + const typename Map::mapped_type&>::value>::type> +const typename Map::mapped_type& get_ref_default( + const Map& map, + const typename Map::key_type& key, + Func&& dflt) { + auto pos = map.find(key); + return (pos != map.end() ? pos->second : dflt()); +} + /** * Given a map and a key, return a pointer to the value corresponding to the * key in the map, or nullptr if the key doesn't exist in the map. diff --git a/folly/test/MapUtilTest.cpp b/folly/test/MapUtilTest.cpp index 4e21fd0a..d31881b1 100644 --- a/folly/test/MapUtilTest.cpp +++ b/folly/test/MapUtilTest.cpp @@ -29,6 +29,14 @@ TEST(MapUtil, get_default) { EXPECT_EQ(0, get_default(m, 3)); } +TEST(MapUtil, get_default_function) { + std::map m; + m[1] = 2; + EXPECT_EQ(2, get_default(m, 1, [] { return 42; })); + EXPECT_EQ(42, get_default(m, 2, [] { return 42; })); + EXPECT_EQ(0, get_default(m, 3)); +} + TEST(MapUtil, get_or_throw) { std::map m; m[1] = 2; @@ -57,6 +65,19 @@ TEST(MapUtil, get_ref_default) { const int i = 42; EXPECT_EQ(2, get_ref_default(m, 1, i)); EXPECT_EQ(42, get_ref_default(m, 2, i)); + EXPECT_EQ(std::addressof(i), std::addressof(get_ref_default(m, 2, i))); +} + +TEST(MapUtil, get_ref_default_function) { + std::map m; + m[1] = 2; + const int i = 42; + EXPECT_EQ(2, get_ref_default(m, 1, [&i]() -> const int& { return i; })); + EXPECT_EQ(42, get_ref_default(m, 2, [&i]() -> const int& { return i; })); + EXPECT_EQ( + std::addressof(i), + std::addressof( + get_ref_default(m, 2, [&i]() -> const int& { return i; }))); } TEST(MapUtil, get_ptr) { -- 2.34.1