Skip to content

Commit

Permalink
Add extra operator[] overload templates to address issue nlohmann#171
Browse files Browse the repository at this point in the history
  • Loading branch information
Trevor Welsby committed Jan 22, 2016
1 parent 304ccdb commit 80877ad
Show file tree
Hide file tree
Showing 3 changed files with 193 additions and 16 deletions.
80 changes: 72 additions & 8 deletions src/json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3272,8 +3272,6 @@ class basic_json
the object and filled with a `null` value to make `key` a valid reference.
In case the value was `null` before, it is converted to an object.
@note This function is required for compatibility reasons with Clang.
@param[in] key key of the element to access
@return reference to the element at key @a key
Expand All @@ -3293,7 +3291,75 @@ class basic_json
@since version 1.0.0
*/
template<typename T, std::size_t n>
reference operator[](const T (&key)[n])
reference operator[](T* (&key)[n])
{
return operator[](static_cast<const T>(key));
}

/*!
@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; example: `"cannot use
operator[] with null"`
@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.0
*/
template<typename T, std::size_t n>
const_reference operator[](T* (&key)[n]) const
{
return operator[](static_cast<const T>(key));
}

/*!
@brief access specified object element
Returns a reference to the element at with specified key @a key.
@note If @a key is not found in the object, then it is silently added to
the object and filled with a `null` value to make `key` a valid reference.
In case the value was `null` before, it is converted to an object.
@param[in] key key of the element to access
@return reference to the element at key @a key
@throw std::domain_error if JSON is not an object or null; example:
`"cannot use operator[] with null"`
@complexity Logarithmic in the size of the container.
@liveexample{The example below shows how object elements can be read and
written using the [] operator.,operatorarray__key_type}
@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 2.0.0
*/
template<typename T>
reference operator[](T* key)
{
// implicitly convert null to object
if (is_null())
Expand Down Expand Up @@ -3323,8 +3389,6 @@ class basic_json
@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
Expand All @@ -3341,10 +3405,10 @@ class basic_json
with range checking
@sa @ref value() for access by value with a default value
@since version 1.0.0
@since version 2.0.0
*/
template<typename T, std::size_t n>
const_reference operator[](const T (&key)[n]) const
template<typename T>
const_reference operator[](T* key) const
{
// at only works for objects
if (is_object())
Expand Down
80 changes: 72 additions & 8 deletions src/json.hpp.re2c
Original file line number Diff line number Diff line change
Expand Up @@ -3272,8 +3272,6 @@ class basic_json
the object and filled with a `null` value to make `key` a valid reference.
In case the value was `null` before, it is converted to an object.

@note This function is required for compatibility reasons with Clang.

@param[in] key key of the element to access

@return reference to the element at key @a key
Expand All @@ -3293,7 +3291,75 @@ class basic_json
@since version 1.0.0
*/
template<typename T, std::size_t n>
reference operator[](const T (&key)[n])
reference operator[](T* (&key)[n])
{
return operator[](static_cast<const T>(key));
}

/*!
@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; example: `"cannot use
operator[] with null"`

@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.0
*/
template<typename T, std::size_t n>
const_reference operator[](T* (&key)[n]) const
{
return operator[](static_cast<const T>(key));
}

/*!
@brief access specified object element

Returns a reference to the element at with specified key @a key.

@note If @a key is not found in the object, then it is silently added to
the object and filled with a `null` value to make `key` a valid reference.
In case the value was `null` before, it is converted to an object.

@param[in] key key of the element to access

@return reference to the element at key @a key

@throw std::domain_error if JSON is not an object or null; example:
`"cannot use operator[] with null"`

@complexity Logarithmic in the size of the container.

@liveexample{The example below shows how object elements can be read and
written using the [] operator.,operatorarray__key_type}

@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 2.0.0
*/
template<typename T>
reference operator[](T* key)
{
// implicitly convert null to object
if (is_null())
Expand Down Expand Up @@ -3323,8 +3389,6 @@ class basic_json
@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
Expand All @@ -3341,10 +3405,10 @@ class basic_json
with range checking
@sa @ref value() for access by value with a default value

@since version 1.0.0
@since version 2.0.0
*/
template<typename T, std::size_t n>
const_reference operator[](const T (&key)[n]) const
template<typename T>
const_reference operator[](T* key) const
{
// at only works for objects
if (is_object())
Expand Down
49 changes: 49 additions & 0 deletions test/unit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12201,5 +12201,54 @@ TEST_CASE("regression tests")
{
CHECK(json::parse("\"\\ud80c\\udc60abc\"").get<json::string_t>() == u8"\U00013060abc");
}


SECTION("issue #144 - Cannot index by key of type static constexpr const char*")
{
json j;

// Non-const access with key as "char []"
char array_key[] = "Key1";
CHECK_NOTHROW(j[array_key] = 1);
CHECK(j[array_key] == json(1));

// Non-const access with key as "const char[]"
const char const_array_key[] = "Key2";
CHECK_NOTHROW(j[const_array_key] = 2);
CHECK(j[const_array_key] == json(2));

// Non-const access with key as "char *"
char _ptr_key[] = "Key3";
char * ptr_key = &_ptr_key[0];
CHECK_NOTHROW(j[ptr_key] = 3);
CHECK(j[ptr_key] == json(3));

// Non-const access with key as "const char *"
const char * const_ptr_key = "Key4";
CHECK_NOTHROW(j[const_ptr_key] = 4);
CHECK(j[const_ptr_key] == json(4));

// Non-const access with key as "static constexpr const char *"
static constexpr const char* constexpr_ptr_key = "Key5";
CHECK_NOTHROW(j[constexpr_ptr_key] = 5);
CHECK(j[constexpr_ptr_key] == json(5));

const json j_const = j;

// Non-const access with key as "char []"
CHECK(j_const[array_key] == json(1));

// Non-const access with key as "const char[]"
CHECK(j_const[const_array_key] == json(2));

// Non-const access with key as "char *"
CHECK(j_const[ptr_key] == json(3));

// Non-const access with key as "const char *"
CHECK(j_const[const_ptr_key] == json(4));

// Non-const access with key as "static constexpr const char *"
CHECK(j_const[constexpr_ptr_key] == json(5));
}
}

0 comments on commit 80877ad

Please sign in to comment.