It was a good idea to implement a const version of operator[] it in the first place. I was a pity that this implementation was flawed. It was a mistake to remove the const version completely. This commit re-introduces the const version. My apologies for all the inconvenience.
This commit is contained in:
parent
9def0186be
commit
4351698c83
5 changed files with 197 additions and 2 deletions
|
@ -5,7 +5,7 @@ using namespace nlohmann;
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
// create a JSON object
|
// create a JSON object
|
||||||
json object =
|
const json object =
|
||||||
{
|
{
|
||||||
{"one", 1}, {"two", 2}, {"three", 2.9}
|
{"one", 1}, {"two", 2}, {"three", 2.9}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
<a target="_blank" href="http://melpon.org/wandbox/permlink/9X5Q8p7DlWA6v0Ey"><b>online</b></a>
|
<a target="_blank" href="http://melpon.org/wandbox/permlink/4WLxv7id8P64Q1KI"><b>online</b></a>
|
81
src/json.hpp
81
src/json.hpp
|
@ -2862,6 +2862,45 @@ class basic_json
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief read-only access specified object element
|
||||||
|
|
||||||
|
Returns a const reference to the element at with specified key @a key. No
|
||||||
|
bounds checking is performed.
|
||||||
|
|
||||||
|
@warning If the element with key @a key does not exist, the behavior is
|
||||||
|
undefined.
|
||||||
|
|
||||||
|
@param[in] key key of the element to access
|
||||||
|
|
||||||
|
@return const reference to the element at key @a key
|
||||||
|
|
||||||
|
@throw std::domain_error if JSON is not an object
|
||||||
|
|
||||||
|
@complexity Logarithmic in the size of the container.
|
||||||
|
|
||||||
|
@liveexample{The example below shows how object elements can be read using
|
||||||
|
the [] operator.,operatorarray__key_type_const}
|
||||||
|
|
||||||
|
@sa @ref at(const typename object_t::key_type&) for access by reference
|
||||||
|
with range checking
|
||||||
|
@sa @ref value() for access by value with a default value
|
||||||
|
|
||||||
|
@since version 1.0
|
||||||
|
*/
|
||||||
|
const_reference operator[](const typename object_t::key_type& key) const
|
||||||
|
{
|
||||||
|
// [] only works for objects
|
||||||
|
if (is_object())
|
||||||
|
{
|
||||||
|
return m_value.object->find(key)->second;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw std::domain_error("cannot use operator[] with " + type_name());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief access specified object element
|
@brief access specified object element
|
||||||
|
|
||||||
|
@ -2911,6 +2950,48 @@ class basic_json
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief read-only access specified object element
|
||||||
|
|
||||||
|
Returns a const reference to the element at with specified key @a key. No
|
||||||
|
bounds checking is performed.
|
||||||
|
|
||||||
|
@warning If the element with key @a key does not exist, the behavior is
|
||||||
|
undefined.
|
||||||
|
|
||||||
|
@note This function is required for compatibility reasons with Clang.
|
||||||
|
|
||||||
|
@param[in] key key of the element to access
|
||||||
|
|
||||||
|
@return const reference to the element at key @a key
|
||||||
|
|
||||||
|
@throw std::domain_error if JSON is not an object
|
||||||
|
|
||||||
|
@complexity Logarithmic in the size of the container.
|
||||||
|
|
||||||
|
@liveexample{The example below shows how object elements can be read using
|
||||||
|
the [] operator.,operatorarray__key_type_const}
|
||||||
|
|
||||||
|
@sa @ref at(const typename object_t::key_type&) for access by reference
|
||||||
|
with range checking
|
||||||
|
@sa @ref value() for access by value with a default value
|
||||||
|
|
||||||
|
@since version 1.0
|
||||||
|
*/
|
||||||
|
template<typename T, std::size_t n>
|
||||||
|
const_reference operator[](const T (&key)[n]) const
|
||||||
|
{
|
||||||
|
// at only works for objects
|
||||||
|
if (is_object())
|
||||||
|
{
|
||||||
|
return m_value.object->find(key)->second;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw std::domain_error("cannot use operator[] with " + type_name());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief access specified object element with default value
|
@brief access specified object element with default value
|
||||||
|
|
||||||
|
|
|
@ -2862,6 +2862,45 @@ class basic_json
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief read-only access specified object element
|
||||||
|
|
||||||
|
Returns a const reference to the element at with specified key @a key. No
|
||||||
|
bounds checking is performed.
|
||||||
|
|
||||||
|
@warning If the element with key @a key does not exist, the behavior is
|
||||||
|
undefined.
|
||||||
|
|
||||||
|
@param[in] key key of the element to access
|
||||||
|
|
||||||
|
@return const reference to the element at key @a key
|
||||||
|
|
||||||
|
@throw std::domain_error if JSON is not an object
|
||||||
|
|
||||||
|
@complexity Logarithmic in the size of the container.
|
||||||
|
|
||||||
|
@liveexample{The example below shows how object elements can be read using
|
||||||
|
the [] operator.,operatorarray__key_type_const}
|
||||||
|
|
||||||
|
@sa @ref at(const typename object_t::key_type&) for access by reference
|
||||||
|
with range checking
|
||||||
|
@sa @ref value() for access by value with a default value
|
||||||
|
|
||||||
|
@since version 1.0
|
||||||
|
*/
|
||||||
|
const_reference operator[](const typename object_t::key_type& key) const
|
||||||
|
{
|
||||||
|
// [] only works for objects
|
||||||
|
if (is_object())
|
||||||
|
{
|
||||||
|
return m_value.object->find(key)->second;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw std::domain_error("cannot use operator[] with " + type_name());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief access specified object element
|
@brief access specified object element
|
||||||
|
|
||||||
|
@ -2911,6 +2950,48 @@ class basic_json
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief read-only access specified object element
|
||||||
|
|
||||||
|
Returns a const reference to the element at with specified key @a key. No
|
||||||
|
bounds checking is performed.
|
||||||
|
|
||||||
|
@warning If the element with key @a key does not exist, the behavior is
|
||||||
|
undefined.
|
||||||
|
|
||||||
|
@note This function is required for compatibility reasons with Clang.
|
||||||
|
|
||||||
|
@param[in] key key of the element to access
|
||||||
|
|
||||||
|
@return const reference to the element at key @a key
|
||||||
|
|
||||||
|
@throw std::domain_error if JSON is not an object
|
||||||
|
|
||||||
|
@complexity Logarithmic in the size of the container.
|
||||||
|
|
||||||
|
@liveexample{The example below shows how object elements can be read using
|
||||||
|
the [] operator.,operatorarray__key_type_const}
|
||||||
|
|
||||||
|
@sa @ref at(const typename object_t::key_type&) for access by reference
|
||||||
|
with range checking
|
||||||
|
@sa @ref value() for access by value with a default value
|
||||||
|
|
||||||
|
@since version 1.0
|
||||||
|
*/
|
||||||
|
template<typename T, std::size_t n>
|
||||||
|
const_reference operator[](const T (&key)[n]) const
|
||||||
|
{
|
||||||
|
// at only works for objects
|
||||||
|
if (is_object())
|
||||||
|
{
|
||||||
|
return m_value.object->find(key)->second;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw std::domain_error("cannot use operator[] with " + type_name());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief access specified object element with default value
|
@brief access specified object element with default value
|
||||||
|
|
||||||
|
|
|
@ -3211,6 +3211,27 @@ TEST_CASE("element access")
|
||||||
|
|
||||||
CHECK(j["array"] == json({1, 2, 3}));
|
CHECK(j["array"] == json({1, 2, 3}));
|
||||||
CHECK(j[json::object_t::key_type("array")] == j["array"]);
|
CHECK(j[json::object_t::key_type("array")] == j["array"]);
|
||||||
|
|
||||||
|
CHECK(j_const["integer"] == json(1));
|
||||||
|
CHECK(j_const[json::object_t::key_type("integer")] == j["integer"]);
|
||||||
|
|
||||||
|
CHECK(j_const["boolean"] == json(true));
|
||||||
|
CHECK(j_const[json::object_t::key_type("boolean")] == j["boolean"]);
|
||||||
|
|
||||||
|
CHECK(j_const["null"] == json(nullptr));
|
||||||
|
CHECK(j_const[json::object_t::key_type("null")] == j["null"]);
|
||||||
|
|
||||||
|
CHECK(j_const["string"] == json("hello world"));
|
||||||
|
CHECK(j_const[json::object_t::key_type("string")] == j["string"]);
|
||||||
|
|
||||||
|
CHECK(j_const["floating"] == json(42.23));
|
||||||
|
CHECK(j_const[json::object_t::key_type("floating")] == j["floating"]);
|
||||||
|
|
||||||
|
CHECK(j_const["object"] == json(json::object()));
|
||||||
|
CHECK(j_const[json::object_t::key_type("object")] == j["object"]);
|
||||||
|
|
||||||
|
CHECK(j_const["array"] == json({1, 2, 3}));
|
||||||
|
CHECK(j_const[json::object_t::key_type("array")] == j["array"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("access on non-object type")
|
SECTION("access on non-object type")
|
||||||
|
@ -3222,6 +3243,8 @@ TEST_CASE("element access")
|
||||||
const json j_const_nonobject(j_nonobject);
|
const json j_const_nonobject(j_nonobject);
|
||||||
CHECK_NOTHROW(j_nonobject["foo"]);
|
CHECK_NOTHROW(j_nonobject["foo"]);
|
||||||
CHECK_NOTHROW(j_nonobject2[json::object_t::key_type("foo")]);
|
CHECK_NOTHROW(j_nonobject2[json::object_t::key_type("foo")]);
|
||||||
|
CHECK_THROWS_AS(j_const_nonobject["foo"], std::domain_error);
|
||||||
|
CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("boolean")
|
SECTION("boolean")
|
||||||
|
@ -3230,6 +3253,8 @@ TEST_CASE("element access")
|
||||||
const json j_const_nonobject(j_nonobject);
|
const json j_const_nonobject(j_nonobject);
|
||||||
CHECK_THROWS_AS(j_nonobject["foo"], std::domain_error);
|
CHECK_THROWS_AS(j_nonobject["foo"], std::domain_error);
|
||||||
CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], std::domain_error);
|
CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], std::domain_error);
|
||||||
|
CHECK_THROWS_AS(j_const_nonobject["foo"], std::domain_error);
|
||||||
|
CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("string")
|
SECTION("string")
|
||||||
|
@ -3238,6 +3263,8 @@ TEST_CASE("element access")
|
||||||
const json j_const_nonobject(j_nonobject);
|
const json j_const_nonobject(j_nonobject);
|
||||||
CHECK_THROWS_AS(j_nonobject["foo"], std::domain_error);
|
CHECK_THROWS_AS(j_nonobject["foo"], std::domain_error);
|
||||||
CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], std::domain_error);
|
CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], std::domain_error);
|
||||||
|
CHECK_THROWS_AS(j_const_nonobject["foo"], std::domain_error);
|
||||||
|
CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("array")
|
SECTION("array")
|
||||||
|
@ -3246,6 +3273,8 @@ TEST_CASE("element access")
|
||||||
const json j_const_nonobject(j_nonobject);
|
const json j_const_nonobject(j_nonobject);
|
||||||
CHECK_THROWS_AS(j_nonobject["foo"], std::domain_error);
|
CHECK_THROWS_AS(j_nonobject["foo"], std::domain_error);
|
||||||
CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], std::domain_error);
|
CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], std::domain_error);
|
||||||
|
CHECK_THROWS_AS(j_const_nonobject["foo"], std::domain_error);
|
||||||
|
CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("number (integer)")
|
SECTION("number (integer)")
|
||||||
|
@ -3254,6 +3283,8 @@ TEST_CASE("element access")
|
||||||
const json j_const_nonobject(j_nonobject);
|
const json j_const_nonobject(j_nonobject);
|
||||||
CHECK_THROWS_AS(j_nonobject["foo"], std::domain_error);
|
CHECK_THROWS_AS(j_nonobject["foo"], std::domain_error);
|
||||||
CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], std::domain_error);
|
CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], std::domain_error);
|
||||||
|
CHECK_THROWS_AS(j_const_nonobject["foo"], std::domain_error);
|
||||||
|
CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("number (floating-point)")
|
SECTION("number (floating-point)")
|
||||||
|
@ -3262,6 +3293,8 @@ TEST_CASE("element access")
|
||||||
const json j_const_nonobject(j_nonobject);
|
const json j_const_nonobject(j_nonobject);
|
||||||
CHECK_THROWS_AS(j_nonobject["foo"], std::domain_error);
|
CHECK_THROWS_AS(j_nonobject["foo"], std::domain_error);
|
||||||
CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], std::domain_error);
|
CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], std::domain_error);
|
||||||
|
CHECK_THROWS_AS(j_const_nonobject["foo"], std::domain_error);
|
||||||
|
CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue