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) && {
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>
dynamic::IfIsNonStringDynamicConvertible<K, dynamic&> dynamic::setDefault(
K&& k,
......
......@@ -206,13 +206,13 @@ dynamic& dynamic::operator[](StringPiece k) & {
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 it = obj.find(k);
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 it = obj.find(k);
// Avoid clang bug with ternary
......@@ -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 it = obj.find(k);
// Avoid clang bug with ternary
......@@ -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 it = obj.find(k);
return std::move(it == obj.end() ? v : it->second);
......
......@@ -497,15 +497,27 @@ struct dynamic : private boost::operators<dynamic> {
* default if it is not yet set, otherwise leaving it. setDefault returns
* 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&;
dynamic getDefault(const dynamic& k, dynamic&& v) const&;
dynamic getDefault(const dynamic& k, const dynamic& v = dynamic::object) &&;
dynamic getDefault(const dynamic& k, dynamic&& v) &&;
template <typename K>
IfIsNonStringDynamicConvertible<K, dynamic> getDefault(
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>
IfIsNonStringDynamicConvertible<K, dynamic&> setDefault(K&& k, V&& v);
template <typename V>
dynamic& setDefault(StringPiece k, V&& v);
// MSVC 2015 Update 3 needs these extra overloads because if V were a
......
......@@ -579,6 +579,7 @@ std::string make_long_string() {
TEST(Dynamic, GetDefault) {
const auto s = make_long_string();
dynamic kDynamicKey{10};
dynamic ds(s);
dynamic tmp(s);
dynamic d1 = dynamic::object("key1", s);
......@@ -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("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);
// lvalue - rvalue
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_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
tmp = s;
EXPECT_EQ(ds, std::move(d1).getDefault("key1", ayy));
......@@ -603,6 +624,21 @@ TEST(Dynamic, GetDefault) {
EXPECT_EQ(ds, std::move(d2).getDefault("not-a-key", tmp));
EXPECT_EQ(dynamic(dynamic::object("key2", s)), d2);
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
EXPECT_EQ(ds, std::move(d3).getDefault("key3", std::move(tmp)));
EXPECT_NE(ds, d3["key3"]);
......@@ -610,6 +646,26 @@ TEST(Dynamic, GetDefault) {
EXPECT_EQ(ds, std::move(d4).getDefault("not-a-key", 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::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) {
......
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