From: Nick Terrell Date: Mon, 27 Mar 2017 20:03:02 +0000 (-0700) Subject: Disallow temporary default values in get_ref_default() X-Git-Tag: v2017.04.03.00~19 X-Git-Url: http://plrg.eecs.uci.edu/git/?p=folly.git;a=commitdiff_plain;h=136c9fba2f6b520946edb2556e1acb14d59ac660;hp=4cc8030e3bdc894c3979529e025c3160fd39ecd9 Disallow temporary default values in get_ref_default() Summary: Passing a temporary default value to `get_ref_default()` returns a dangling reference when it is used. Reviewed By: lbrandy, yfeldblum Differential Revision: D4768769 fbshipit-source-id: 4c58a17dc7662ad553cf88a8544dae20016d2f6f --- diff --git a/folly/MapUtil.h b/folly/MapUtil.h index 063bb0f4..77e092f6 100644 --- a/folly/MapUtil.h +++ b/folly/MapUtil.h @@ -106,6 +106,24 @@ const typename Map::mapped_type& get_ref_default( return (pos != map.end() ? pos->second : dflt); } +/** + * Passing a temporary default value returns a dangling reference when it is + * returned. Lifetime extension is broken by the indirection. + * The caller must ensure that the default value outlives the reference returned + * by get_ref_default(). + */ +template +const typename Map::mapped_type& get_ref_default( + const Map& map, + const typename Map::key_type& key, + typename Map::mapped_type&& dflt) = delete; + +template +const typename Map::mapped_type& get_ref_default( + const Map& map, + const typename Map::key_type& key, + const typename Map::mapped_type&& dflt) = delete; + /** * 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 diff --git a/folly/test/MapUtilTest.cpp b/folly/test/MapUtilTest.cpp index 1fa91df0..33ffe066 100644 --- a/folly/test/MapUtilTest.cpp +++ b/folly/test/MapUtilTest.cpp @@ -19,6 +19,7 @@ #include #include +#include #include using namespace folly; @@ -138,3 +139,23 @@ TEST(MapUtil, get_ptr_path_mixed) { EXPECT_TRUE(get_ptr(cm, "a", 1, "b")); EXPECT_FALSE(get_ptr(cm, "b", 1, "b")); } + +namespace { +template +struct Compiles : std::false_type {}; + +template +struct Compiles< + T, + void_t::type>>(), + std::declval(), + std::declval()))>> : std::true_type {}; +} + +TEST(MapUtil, get_default_temporary) { + EXPECT_TRUE(Compiles::value); + EXPECT_TRUE(Compiles::value); + EXPECT_FALSE(Compiles::value); + EXPECT_FALSE(Compiles::value); +}