Skip to content

Commit

Permalink
✨ added return value for emplace (#349)
Browse files Browse the repository at this point in the history
  • Loading branch information
nlohmann committed Nov 28, 2016
1 parent 6ecff31 commit aeb4f87
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 20 deletions.
9 changes: 8 additions & 1 deletion doc/examples/emplace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,18 @@ int main()
std::cout << null << '\n';

// add values
object.emplace("three", 3);
auto res1 = object.emplace("three", 3);
null.emplace("A", "a");
null.emplace("B", "b");

// the following call will not add an object, because there is already
// a value stored at key "B"
auto res2 = null.emplace("B", "c");

// print values
std::cout << object << '\n';
std::cout << *res1.first << " " << std::boolalpha << res1.second << '\n';

std::cout << null << '\n';
std::cout << *res2.first << " " << std::boolalpha << res2.second << '\n';
}
2 changes: 1 addition & 1 deletion doc/examples/emplace.link
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<a target="_blank" href="http://melpon.org/wandbox/permlink/Qg5Ogrh8yFrwT2GY"><b>online</b></a>
<a target="_blank" href="http://melpon.org/wandbox/permlink/B6ILaoysGMliouEO"><b>online</b></a>
2 changes: 2 additions & 0 deletions doc/examples/emplace.output
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
{"one":1,"two":2}
null
{"one":1,"three":3,"two":2}
3 true
{"A":"a","B":"b"}
"b" false
26 changes: 19 additions & 7 deletions src/json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5075,28 +5075,34 @@ class basic_json
}

/*!
@brief add an object to an object
@brief add an object to an object if key does not exist
Creates a JSON value from the passed parameters @a args to the JSON
object. If the function is called on a JSON null value, an empty object
is created before appending the value created from @a args.
Inserts a new element into a JSON object constructed in-place with the given
@a args if there is no element with the key in the container. If the
function is called on a JSON null value, an empty object is created before
appending the value created from @a args.
@param[in] args arguments to forward to a constructor of @ref basic_json
@tparam Args compatible types to create a @ref basic_json object
@return 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.
@throw std::domain_error when called on a type other than JSON object or
null; example: `"cannot use emplace() with number"`
@complexity Logarithmic in the size of the container, O(log(`size()`)).
@liveexample{The example shows how `emplace()` can be used to add elements
to a JSON object. Note how the `null` value was silently converted to a
JSON object.,emplace}
JSON object. Further note how no value is added if there was already one
value stored with the same key.,emplace}
@since version 2.0.8
*/
template<class... Args>
void emplace(Args&& ... args)
std::pair<iterator, bool> emplace(Args&& ... args)
{
// emplace only works for null objects or arrays
if (not(is_null() or is_object()))
Expand All @@ -5113,7 +5119,13 @@ class basic_json
}

// add element to array (perfect forwarding)
m_value.object->emplace(std::forward<Args>(args)...);
auto res = m_value.object->emplace(std::forward<Args>(args)...);
// create result iterator and set iterator to the result of emplace
auto it = begin();
it.m_it.object_iterator = res.first;

// return pair of iterator and boolean
return {it, res.second};
}

/*!
Expand Down
26 changes: 19 additions & 7 deletions src/json.hpp.re2c
Original file line number Diff line number Diff line change
Expand Up @@ -5075,28 +5075,34 @@ class basic_json
}

/*!
@brief add an object to an object
@brief add an object to an object if key does not exist

Creates a JSON value from the passed parameters @a args to the JSON
object. If the function is called on a JSON null value, an empty object
is created before appending the value created from @a args.
Inserts a new element into a JSON object constructed in-place with the given
@a args if there is no element with the key in the container. If the
function is called on a JSON null value, an empty object is created before
appending the value created from @a args.

@param[in] args arguments to forward to a constructor of @ref basic_json
@tparam Args compatible types to create a @ref basic_json object

@return 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.

@throw std::domain_error when called on a type other than JSON object or
null; example: `"cannot use emplace() with number"`

@complexity Logarithmic in the size of the container, O(log(`size()`)).

@liveexample{The example shows how `emplace()` can be used to add elements
to a JSON object. Note how the `null` value was silently converted to a
JSON object.,emplace}
JSON object. Further note how no value is added if there was already one
value stored with the same key.,emplace}

@since version 2.0.8
*/
template<class... Args>
void emplace(Args&& ... args)
std::pair<iterator, bool> emplace(Args&& ... args)
{
// emplace only works for null objects or arrays
if (not(is_null() or is_object()))
Expand All @@ -5113,7 +5119,13 @@ class basic_json
}

// add element to array (perfect forwarding)
m_value.object->emplace(std::forward<Args>(args)...);
auto res = m_value.object->emplace(std::forward<Args>(args)...);
// create result iterator and set iterator to the result of emplace
auto it = begin();
it.m_it.object_iterator = res.first;

// return pair of iterator and boolean
return {it, res.second};
}

/*!
Expand Down
37 changes: 33 additions & 4 deletions test/src/unit-modifiers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -302,18 +302,47 @@ TEST_CASE("modifiers")
{
SECTION("null")
{
// start with a null value
json j;
j.emplace("foo", "bar");
j.emplace("baz", "bam");

// add a new key
auto res1 = j.emplace("foo", "bar");
CHECK(res1.second == true);
CHECK(*res1.first == "bar");

// the null value is changed to an object
CHECK(j.type() == json::value_t::object);

// add a new key
auto res2 = j.emplace("baz", "bam");
CHECK(res2.second == true);
CHECK(*res2.first == "bam");

// we try to insert at given key - no change
auto res3 = j.emplace("baz", "bad");
CHECK(res3.second == false);
CHECK(*res3.first == "bam");

// the final object
CHECK(j == json({{"baz", "bam"}, {"foo", "bar"}}));
}

SECTION("object")
{
// start with an object
json j = {{"foo", "bar"}};
j.emplace("baz", "bam");
CHECK(j.type() == json::value_t::object);

// add a new key
auto res1 = j.emplace("baz", "bam");
CHECK(res1.second == true);
CHECK(*res1.first == "bam");

// add an existing key
auto res2 = j.emplace("foo", "bad");
CHECK(res2.second == false);
CHECK(*res2.first == "bar");

// check final object
CHECK(j == json({{"baz", "bam"}, {"foo", "bar"}}));
}
}
Expand Down

0 comments on commit aeb4f87

Please sign in to comment.