Commit 95f1ce0f authored by Adam Norton's avatar Adam Norton Committed by Facebook GitHub Bot

dynamic try_emplace

Summary: Expose `try_emplace` to give clients signal on whether an element was actually inserted. This will allow for more efficient code without needing to check for existence before inserting.

Reviewed By: yfeldblum

Differential Revision: D34006997

fbshipit-source-id: 3bdb7d4d81c19d0fcd7c82f194f1f695b79cf57b
parent d2331436
......@@ -843,6 +843,20 @@ inline dynamic::IfNotIterator<K, void> dynamic::insert(K&& key, V&& val) {
obj[std::forward<K>(key)] = std::forward<V>(val);
}
template <class... Args>
inline std::pair<dynamic::item_iterator, bool> dynamic::emplace(
Args&&... args) {
auto& obj = get<ObjectImpl>();
return obj.emplace(std::forward<Args>(args)...);
}
template <class K, class... Args>
inline std::pair<dynamic::item_iterator, bool> dynamic::try_emplace(
K&& key, Args&&... args) {
auto& obj = get<ObjectImpl>();
return obj.try_emplace(std::forward<K>(key), std::forward<Args>(args)...);
}
template <class T>
inline dynamic::iterator dynamic::insert(const_iterator pos, T&& value) {
auto& arr = get<Array>();
......
......@@ -682,6 +682,30 @@ struct dynamic {
template <class K, class V>
IfNotIterator<K, void> insert(K&&, V&& val);
/**
* Inserts an element into an object constructed in-place with the given args
* if there is no existing element with the key, or throws if it's not an
* object. Returns a pair consisting of an iterator to the inserted element,
* or the already existing element if no insertion happened, and a bool
* denoting whether the insertion took place.
*
* Invalidates iterators.
*/
template <class... Args>
std::pair<item_iterator, bool> emplace(Args&&... args);
/**
* Inserts an element into an object with the given key and value constructed
* in-place with the given args if there is no existing element with the key,
* or throws if it's not an object. Returns a pair consisting of an iterator
* to the inserted element, or the already existing element if no insertion
* happened, and a bool denoting whether the insertion took place.
*
* Invalidates iterators.
*/
template <class K, class... Args>
std::pair<item_iterator, bool> try_emplace(K&& key, Args&&... args);
/*
* Inserts the supplied value into array, or throw if not array
* Shifts existing values in the array to the right
......
......@@ -103,6 +103,34 @@ TEST(Dynamic, ObjectBasics) {
dynamic obj2 = dynamic::object;
EXPECT_TRUE(obj2.isObject());
dynamic obj3 = dynamic::object("a", false);
EXPECT_EQ(obj3.at("a"), false);
EXPECT_EQ(obj3.size(), 1);
{
const auto [it, inserted] = obj3.emplace("a", true);
EXPECT_EQ(obj3.size(), 1);
EXPECT_FALSE(inserted);
EXPECT_EQ(it->second, false);
}
{
const auto [it, inserted] = obj3.emplace("b", true);
EXPECT_EQ(obj3.size(), 2);
EXPECT_TRUE(inserted);
EXPECT_EQ(it->second, true);
}
{
const auto [it, inserted] = obj3.try_emplace("a", true);
EXPECT_EQ(obj3.size(), 2);
EXPECT_FALSE(inserted);
EXPECT_EQ(it->second, false);
}
{
const auto [it, inserted] = obj3.try_emplace("c", true);
EXPECT_EQ(obj3.size(), 3);
EXPECT_TRUE(inserted);
EXPECT_EQ(it->second, true);
}
dynamic d3 = nullptr;
EXPECT_TRUE(d3 == nullptr);
d3 = dynamic::object;
......
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