X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2FMapUtil.h;h=d6be57115c7d55d884abf49360f1a7372ec6145b;hb=6f027b290a0ee1754b655b5e739ecb98e11f2f3d;hp=77e092f6ab5b766aedf2d8e1374f2c2d4c44b3b1;hpb=136c9fba2f6b520946edb2556e1acb14d59ac660;p=folly.git diff --git a/folly/MapUtil.h b/folly/MapUtil.h index 77e092f6..d6be5711 100644 --- a/folly/MapUtil.h +++ b/folly/MapUtil.h @@ -18,6 +18,7 @@ #include #include +#include namespace folly { @@ -166,6 +167,8 @@ typename Map::mapped_type* get_ptr( return (pos != map.end() ? &pos->second : nullptr); } +// TODO: Remove the return type computations when clang 3.5 and gcc 5.1 are +// the minimum supported versions. namespace detail { template < class T, @@ -179,6 +182,25 @@ template struct NestedMapType { using type = typename T::mapped_type; }; + +template +struct DefaultType; + +template +struct DefaultType { + using type = Default; +}; + +template +struct DefaultType { + using type = typename DefaultType::type; +}; + +template +auto extract_default(const KeysDefault&... keysDefault) -> + typename DefaultType::type const& { + return std::get(std::tie(keysDefault...)); +} } /** @@ -203,4 +225,53 @@ auto get_ptr(Map& map, const Key1& key1, const Key2& key2, const Keys&... keys) return pos != map.end() ? get_ptr(pos->second, key2, keys...) : nullptr; } +/** + * Given a map and a path of keys, return the value corresponding to the nested + * value, or a given default value if the path doesn't exist in the map. + * The default value is the last parameter, and is copied when returned. + */ +template < + class Map, + class Key1, + class Key2, + class... KeysDefault, + typename = typename std::enable_if::type> +auto get_default( + const Map& map, + const Key1& key1, + const Key2& key2, + const KeysDefault&... keysDefault) -> + typename detail::NestedMapType::type { + if (const auto* ptr = get_ptr(map, key1)) { + return get_default(*ptr, key2, keysDefault...); + } + return detail::extract_default(keysDefault...); +} + +/** + * Given a map and a path of keys, return a reference to the value corresponding + * to the nested value, or the given default reference if the path doesn't exist + * in the map. + * The default value is the last parameter, and must be a lvalue reference. + */ +template < + class Map, + class Key1, + class Key2, + class... KeysDefault, + typename = typename std::enable_if::type, + typename = typename std::enable_if::type>::value>::type> +auto get_ref_default( + const Map& map, + const Key1& key1, + const Key2& key2, + KeysDefault&&... keysDefault) -> + typename detail::NestedMapType::type + const& { + if (const auto* ptr = get_ptr(map, key1)) { + return get_ref_default(*ptr, key2, keysDefault...); + } + return detail::extract_default(keysDefault...); +} } // namespace folly