Commit 1efbcb1b authored by Amol Bhave's avatar Amol Bhave Committed by Facebook Github Bot

Use Heterogenous lookups for dynamic::getDefault

Summary:
Use heterogenous lookup for dynamic::getDefault for
StringPiece/dynamic keys.

Reviewed By: shixiao

Differential Revision: D10127452

fbshipit-source-id: 3cf28a28373211428ac5352136cf073e6c377b16
parent 1499c179
...@@ -671,6 +671,52 @@ inline dynamic&& dynamic::operator[](StringPiece k) && { ...@@ -671,6 +671,52 @@ inline dynamic&& dynamic::operator[](StringPiece k) && {
return std::move((*this)[k]); return std::move((*this)[k]);
} }
template <typename K>
dynamic::IfIsNonStringDynamicConvertible<K, dynamic> dynamic::getDefault(
K&& k,
const dynamic& v) const& {
auto& obj = get<ObjectImpl>();
auto it = obj.find(std::forward<K>(k));
return it == obj.end() ? v : it->second;
}
template <typename K>
dynamic::IfIsNonStringDynamicConvertible<K, dynamic> dynamic::getDefault(
K&& k,
dynamic&& v) const& {
auto& obj = get<ObjectImpl>();
auto it = obj.find(std::forward<K>(k));
// Avoid clang bug with ternary
if (it == obj.end()) {
return std::move(v);
} else {
return it->second;
}
}
template <typename K>
dynamic::IfIsNonStringDynamicConvertible<K, dynamic> dynamic::getDefault(
K&& k,
const dynamic& v) && {
auto& obj = get<ObjectImpl>();
auto it = obj.find(std::forward<K>(k));
// Avoid clang bug with ternary
if (it == obj.end()) {
return v;
} else {
return std::move(it->second);
}
}
template <typename K>
dynamic::IfIsNonStringDynamicConvertible<K, dynamic> dynamic::getDefault(
K&& k,
dynamic&& v) && {
auto& obj = get<ObjectImpl>();
auto it = obj.find(std::forward<K>(k));
return std::move(it == obj.end() ? v : it->second);
}
template <typename K, typename V> template <typename K, typename V>
dynamic::IfIsNonStringDynamicConvertible<K, dynamic&> dynamic::setDefault( dynamic::IfIsNonStringDynamicConvertible<K, dynamic&> dynamic::setDefault(
K&& k, K&& k,
......
...@@ -206,13 +206,13 @@ dynamic& dynamic::operator[](StringPiece k) & { ...@@ -206,13 +206,13 @@ dynamic& dynamic::operator[](StringPiece k) & {
return ret.first->second; return ret.first->second;
} }
dynamic dynamic::getDefault(const dynamic& k, const dynamic& v) const& { dynamic dynamic::getDefault(StringPiece k, const dynamic& v) const& {
auto& obj = get<ObjectImpl>(); auto& obj = get<ObjectImpl>();
auto it = obj.find(k); auto it = obj.find(k);
return it == obj.end() ? v : it->second; return it == obj.end() ? v : it->second;
} }
dynamic dynamic::getDefault(const dynamic& k, dynamic&& v) const& { dynamic dynamic::getDefault(StringPiece k, dynamic&& v) const& {
auto& obj = get<ObjectImpl>(); auto& obj = get<ObjectImpl>();
auto it = obj.find(k); auto it = obj.find(k);
// Avoid clang bug with ternary // Avoid clang bug with ternary
...@@ -223,7 +223,7 @@ dynamic dynamic::getDefault(const dynamic& k, dynamic&& v) const& { ...@@ -223,7 +223,7 @@ dynamic dynamic::getDefault(const dynamic& k, dynamic&& v) const& {
} }
} }
dynamic dynamic::getDefault(const dynamic& k, const dynamic& v) && { dynamic dynamic::getDefault(StringPiece k, const dynamic& v) && {
auto& obj = get<ObjectImpl>(); auto& obj = get<ObjectImpl>();
auto it = obj.find(k); auto it = obj.find(k);
// Avoid clang bug with ternary // Avoid clang bug with ternary
...@@ -234,7 +234,7 @@ dynamic dynamic::getDefault(const dynamic& k, const dynamic& v) && { ...@@ -234,7 +234,7 @@ dynamic dynamic::getDefault(const dynamic& k, const dynamic& v) && {
} }
} }
dynamic dynamic::getDefault(const dynamic& k, dynamic&& v) && { dynamic dynamic::getDefault(StringPiece k, dynamic&& v) && {
auto& obj = get<ObjectImpl>(); auto& obj = get<ObjectImpl>();
auto it = obj.find(k); auto it = obj.find(k);
return std::move(it == obj.end() ? v : it->second); return std::move(it == obj.end() ? v : it->second);
......
...@@ -497,15 +497,27 @@ struct dynamic : private boost::operators<dynamic> { ...@@ -497,15 +497,27 @@ struct dynamic : private boost::operators<dynamic> {
* default if it is not yet set, otherwise leaving it. setDefault returns * default if it is not yet set, otherwise leaving it. setDefault returns
* a reference to the existing value if present, the new value otherwise. * a reference to the existing value if present, the new value otherwise.
*/ */
dynamic getDefault(const dynamic& k, const dynamic& v = dynamic::object) template <typename K>
IfIsNonStringDynamicConvertible<K, dynamic> getDefault(
K&& k,
const dynamic& v = dynamic::object) const&;
template <typename K>
IfIsNonStringDynamicConvertible<K, dynamic> getDefault(K&& k, dynamic&& v)
const&; const&;
dynamic getDefault(const dynamic& k, dynamic&& v) const&; template <typename K>
dynamic getDefault(const dynamic& k, const dynamic& v = dynamic::object) &&; IfIsNonStringDynamicConvertible<K, dynamic> getDefault(
dynamic getDefault(const dynamic& k, dynamic&& v) &&; K&& k,
const dynamic& v = dynamic::object) &&;
template <typename K>
IfIsNonStringDynamicConvertible<K, dynamic> getDefault(K&& k, dynamic&& v) &&;
dynamic getDefault(StringPiece k, const dynamic& v = dynamic::object) const&;
dynamic getDefault(StringPiece k, dynamic&& v) const&;
dynamic getDefault(StringPiece k, const dynamic& v = dynamic::object) &&;
dynamic getDefault(StringPiece k, dynamic&& v) &&;
template <typename K, typename V> template <typename K, typename V>
IfIsNonStringDynamicConvertible<K, dynamic&> setDefault(K&& k, V&& v); IfIsNonStringDynamicConvertible<K, dynamic&> setDefault(K&& k, V&& v);
template <typename V> template <typename V>
dynamic& setDefault(StringPiece k, V&& v); dynamic& setDefault(StringPiece k, V&& v);
// MSVC 2015 Update 3 needs these extra overloads because if V were a // MSVC 2015 Update 3 needs these extra overloads because if V were a
......
...@@ -579,6 +579,7 @@ std::string make_long_string() { ...@@ -579,6 +579,7 @@ std::string make_long_string() {
TEST(Dynamic, GetDefault) { TEST(Dynamic, GetDefault) {
const auto s = make_long_string(); const auto s = make_long_string();
dynamic kDynamicKey{10};
dynamic ds(s); dynamic ds(s);
dynamic tmp(s); dynamic tmp(s);
dynamic d1 = dynamic::object("key1", s); dynamic d1 = dynamic::object("key1", s);
...@@ -590,12 +591,32 @@ TEST(Dynamic, GetDefault) { ...@@ -590,12 +591,32 @@ TEST(Dynamic, GetDefault) {
EXPECT_EQ(ds, d1.getDefault("key1", ayy)); EXPECT_EQ(ds, d1.getDefault("key1", ayy));
EXPECT_EQ(ds, d1.getDefault("key1", ayy)); EXPECT_EQ(ds, d1.getDefault("key1", ayy));
EXPECT_EQ(ds, d1.getDefault("not-a-key", tmp)); EXPECT_EQ(ds, d1.getDefault("not-a-key", tmp));
EXPECT_EQ(ds, d1.getDefault(StaticStrings::kA, tmp));
EXPECT_EQ(ds, d1.getDefault(StaticStrings::kB, tmp));
EXPECT_EQ(ds, d1.getDefault(StaticStrings::kFoo, tmp));
EXPECT_EQ(ds, d1.getDefault(StaticStrings::kBar, tmp));
EXPECT_EQ(ds, d1.getDefault(kDynamicKey, tmp));
EXPECT_EQ(ds, tmp); EXPECT_EQ(ds, tmp);
// lvalue - rvalue // lvalue - rvalue
EXPECT_EQ(ds, d1.getDefault("key1", "ayy")); EXPECT_EQ(ds, d1.getDefault("key1", "ayy"));
EXPECT_EQ(ds, d1.getDefault("key1", "ayy")); EXPECT_EQ(ds, d1.getDefault("key1", "ayy"));
EXPECT_EQ(ds, d1.getDefault("not-a-key", std::move(tmp))); EXPECT_EQ(ds, d1.getDefault("not-a-key", std::move(tmp)));
EXPECT_NE(ds, tmp); EXPECT_NE(ds, tmp);
tmp = s;
EXPECT_EQ(ds, d1.getDefault(StaticStrings::kA, std::move(tmp)));
EXPECT_NE(ds, tmp);
tmp = s;
EXPECT_EQ(ds, d1.getDefault(StaticStrings::kB, std::move(tmp)));
EXPECT_NE(ds, tmp);
tmp = s;
EXPECT_EQ(ds, d1.getDefault(StaticStrings::kFoo, std::move(tmp)));
EXPECT_NE(ds, tmp);
tmp = s;
EXPECT_EQ(ds, d1.getDefault(StaticStrings::kBar, std::move(tmp)));
EXPECT_NE(ds, tmp);
tmp = s;
EXPECT_EQ(ds, d1.getDefault(kDynamicKey, std::move(tmp)));
EXPECT_NE(ds, tmp);
// rvalue - lvalue // rvalue - lvalue
tmp = s; tmp = s;
EXPECT_EQ(ds, std::move(d1).getDefault("key1", ayy)); EXPECT_EQ(ds, std::move(d1).getDefault("key1", ayy));
...@@ -603,6 +624,21 @@ TEST(Dynamic, GetDefault) { ...@@ -603,6 +624,21 @@ TEST(Dynamic, GetDefault) {
EXPECT_EQ(ds, std::move(d2).getDefault("not-a-key", tmp)); EXPECT_EQ(ds, std::move(d2).getDefault("not-a-key", tmp));
EXPECT_EQ(dynamic(dynamic::object("key2", s)), d2); EXPECT_EQ(dynamic(dynamic::object("key2", s)), d2);
EXPECT_EQ(ds, tmp); EXPECT_EQ(ds, tmp);
EXPECT_EQ(ds, std::move(d2).getDefault(StaticStrings::kA, tmp));
EXPECT_EQ(dynamic(dynamic::object("key2", s)), d2);
EXPECT_EQ(ds, tmp);
EXPECT_EQ(ds, std::move(d2).getDefault(StaticStrings::kB, tmp));
EXPECT_EQ(dynamic(dynamic::object("key2", s)), d2);
EXPECT_EQ(ds, tmp);
EXPECT_EQ(ds, std::move(d2).getDefault(StaticStrings::kFoo, tmp));
EXPECT_EQ(dynamic(dynamic::object("key2", s)), d2);
EXPECT_EQ(ds, tmp);
EXPECT_EQ(ds, std::move(d2).getDefault(StaticStrings::kBar, tmp));
EXPECT_EQ(dynamic(dynamic::object("key2", s)), d2);
EXPECT_EQ(ds, tmp);
EXPECT_EQ(ds, std::move(d2).getDefault(kDynamicKey, tmp));
EXPECT_EQ(dynamic(dynamic::object("key2", s)), d2);
EXPECT_EQ(ds, tmp);
// rvalue - rvalue // rvalue - rvalue
EXPECT_EQ(ds, std::move(d3).getDefault("key3", std::move(tmp))); EXPECT_EQ(ds, std::move(d3).getDefault("key3", std::move(tmp)));
EXPECT_NE(ds, d3["key3"]); EXPECT_NE(ds, d3["key3"]);
...@@ -610,6 +646,26 @@ TEST(Dynamic, GetDefault) { ...@@ -610,6 +646,26 @@ TEST(Dynamic, GetDefault) {
EXPECT_EQ(ds, std::move(d4).getDefault("not-a-key", std::move(tmp))); EXPECT_EQ(ds, std::move(d4).getDefault("not-a-key", std::move(tmp)));
EXPECT_EQ(dynamic(dynamic::object("key4", s)), d4); EXPECT_EQ(dynamic(dynamic::object("key4", s)), d4);
EXPECT_NE(ds, tmp); EXPECT_NE(ds, tmp);
tmp = s;
EXPECT_EQ(ds, std::move(d4).getDefault(StaticStrings::kA, std::move(tmp)));
EXPECT_EQ(dynamic(dynamic::object("key4", s)), d4);
EXPECT_NE(ds, tmp);
tmp = s;
EXPECT_EQ(ds, std::move(d4).getDefault(StaticStrings::kB, std::move(tmp)));
EXPECT_EQ(dynamic(dynamic::object("key4", s)), d4);
EXPECT_NE(ds, tmp);
tmp = s;
EXPECT_EQ(ds, std::move(d4).getDefault(StaticStrings::kFoo, std::move(tmp)));
EXPECT_EQ(dynamic(dynamic::object("key4", s)), d4);
EXPECT_NE(ds, tmp);
tmp = s;
EXPECT_EQ(ds, std::move(d4).getDefault(StaticStrings::kBar, std::move(tmp)));
EXPECT_EQ(dynamic(dynamic::object("key4", s)), d4);
EXPECT_NE(ds, tmp);
tmp = s;
EXPECT_EQ(ds, std::move(d4).getDefault(kDynamicKey, std::move(tmp)));
EXPECT_EQ(dynamic(dynamic::object("key4", s)), d4);
EXPECT_NE(ds, tmp);
} }
TEST(Dynamic, GetString) { TEST(Dynamic, GetString) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment