diff --git a/doc/mkdocs/docs/api/basic_json/erase.md b/doc/mkdocs/docs/api/basic_json/erase.md index 160fe8f35..af53bf01f 100644 --- a/doc/mkdocs/docs/api/basic_json/erase.md +++ b/doc/mkdocs/docs/api/basic_json/erase.md @@ -12,7 +12,6 @@ const_iterator erase(const_iterator first, const_iterator last); // (3) template size_type erase(KeyT && key); -size_type erase(const std::string_view& key); // since C++17 // (4) void erase(const size_type idx); @@ -36,7 +35,7 @@ void erase(const size_type idx); ## Template parameters `KeyT` -: A type convertible to an object key. This can also be a string literal. +: A type convertible to an object key. This can also be a string literal or a string view (C++17). ## Parameters @@ -182,4 +181,4 @@ Strong exception safety: if an exception occurs, the original value stays intact - Added in version 1.0.0. - Added support for binary types in version 3.8.0. -- Added `KeyT` template and overload for `std::string_view` in version 3.10.0. +- Added `KeyT` template in version 3.10.0. diff --git a/include/nlohmann/detail/meta/type_traits.hpp b/include/nlohmann/detail/meta/type_traits.hpp index 1706cbdc6..dc20cc08b 100644 --- a/include/nlohmann/detail/meta/type_traits.hpp +++ b/include/nlohmann/detail/meta/type_traits.hpp @@ -394,5 +394,17 @@ struct is_constructible_tuple : std::false_type {}; template struct is_constructible_tuple> : conjunction...> {}; + +/// type to check if KeyType can be used as object key +template +struct is_key_type +{ + static constexpr bool value = +#if defined(JSON_HAS_CPP_17) + std::is_same::type, std::string_view>::value || +#endif + std::is_convertible::value; +}; + } // namespace detail } // namespace nlohmann diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index 7401be561..c3f658f1f 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -3495,12 +3495,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec written using `at()`. It also demonstrates the different exceptions that can be thrown.,at__object_t_key_type} */ - template < class KeyT, typename std::enable_if < - !std::is_same::type, json_pointer>::value&& ( -#if defined(JSON_HAS_CPP_17) - std::is_same::type, std::string_view>::value || -#endif - std::is_convertible::value), int >::type = 0 > + template < class KeyT, typename detail::enable_if_t < + detail::is_key_type::value&& !std::is_same::type, json_pointer>::value > ... > reference at(const KeyT& key) { // at only works for objects @@ -3548,12 +3544,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec `at()`. It also demonstrates the different exceptions that can be thrown., at__object_t_key_type_const} */ - template < class KeyT, typename std::enable_if < - !std::is_same::type, json_pointer>::value&& ( -#if defined(JSON_HAS_CPP_17) - std::is_same::type, std::string_view>::value || -#endif - std::is_convertible::value), int >::type = 0 > + template < class KeyT, typename detail::enable_if_t < + detail::is_key_type::value&& !std::is_same::type, json_pointer>::value > ... > const_reference at(const KeyT& key) const { // at only works for objects @@ -3687,13 +3679,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec @since version 1.0.0; template KeyT added in version 3.10.0 */ - template < class KeyT, typename std::enable_if < - !std::is_same::type, json_pointer>::value&& ( -#if defined(JSON_HAS_CPP_17) - std::is_same::type, std::string_view>::value || -#endif - std::is_convertible::value), int >::type = 0 > - reference operator[](KeyT && key) + template < class KeyT, typename detail::enable_if_t < + detail::is_key_type::value&& !std::is_same::type, json_pointer>::value > ... > + reference operator[](KeyT&& key) { // implicitly convert null value to an empty object if (is_null()) @@ -3750,13 +3738,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec @since version 1.0.0; template KeyT added in version 3.10.0 */ - template < class KeyT, typename std::enable_if < - !std::is_same::type, json_pointer>::value&& ( -#if defined(JSON_HAS_CPP_17) - std::is_same::type, std::string_view>::value || -#endif - std::is_convertible::value), int >::type = 0 > - const_reference operator[](KeyT && key) const + template < class KeyT, typename detail::enable_if_t < + detail::is_key_type::value&& !std::is_same::type, json_pointer>::value > ... > + const_reference operator[](KeyT&& key) const { // operator[] only works for objects if (JSON_HEDLEY_LIKELY(is_object())) @@ -3822,13 +3806,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec @since version 1.0.0, KeyType template added in 3.10.0 */ // using std::is_convertible in a std::enable_if will fail when using explicit conversions - template < class KeyType, class ValueType, typename std::enable_if < + template < class KeyType, class ValueType, typename detail::enable_if_t < detail::is_getable::value - && !std::is_same::value&& ( -#if defined(JSON_HAS_CPP_17) - std::is_same::value || -#endif - std::is_convertible::value), int >::type = 0 > + && !std::is_same::value&& detail::is_key_type::value > ... > ValueType value(const KeyType& key, const ValueType& default_value) const { // at only works for objects @@ -3851,11 +3831,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec @brief overload for a default value of type const char* @copydoc basic_json::value(const typename object_t::key_type&, const ValueType&) const */ - template < class KeyType, typename std::enable_if < -#if defined(JSON_HAS_CPP_17) - std::is_same::value || -#endif - std::is_convertible::value, int >::type = 0 > + template < class KeyType, typename detail::enable_if_t < + detail::is_key_type::value > ... > string_t value(const KeyType& key, const char* default_value) const { return value(key, string_t(default_value)); @@ -4256,7 +4233,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec Removes elements from a JSON object with the key value @a key. @param[in] key value of the elements to remove - @tparam KeyT a type convertible to an object key + @tparam KeyT a type convertible to an object key or a std::string_view @return Number of elements removed. If @a ObjectType is the default `std::map` type, the return value will always be `0` (@a key was not @@ -4280,53 +4257,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec @since version 1.0.0; template added in version 3.10.0 */ - template < class KeyT, typename std::enable_if < -#if defined(JSON_HAS_CPP_17) - !std::is_same::type, std::string_view>::value&& -#endif - std::is_convertible::value, int >::type = 0 > - size_type erase(KeyT && key) - { - // this erase only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - return m_value.object->erase(std::forward(key)); - } - - JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this)); - } - -#if defined(JSON_HAS_CPP_17) - /*! - @brief remove element from a JSON object given a key - - Removes elements from a JSON object with the key value @a key. - - @param[in] key value of the elements to remove - - @return Number of elements removed. If @a ObjectType is the default - `std::map` type, the return value will always be `0` (@a key was not - found) or `1` (@a key was found). - - @post References and iterators to the erased elements are invalidated. - Other references and iterators are not affected. - - @throw type_error.307 when called on a type other than JSON object; - example: `"cannot use erase() with null"` - - @complexity `log(size()) + count(key)` - - @liveexample{The example shows the effect of `erase()`.,erase__key_type} - - @sa see @ref erase(IteratorType) -- removes the element at a given position - @sa see @ref erase(IteratorType, IteratorType) -- removes the elements in - the given range - @sa see @ref erase(const size_type) -- removes the element from an array at - the given index - - @since version 3.10.0 - */ - size_type erase(const std::string_view& key) + template < class KeyT, typename detail::enable_if_t < + detail::is_key_type::value > ... > + size_type erase(KeyT&& key) { // this erase only works for objects if (JSON_HEDLEY_UNLIKELY(!is_object())) @@ -4343,7 +4276,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec return 0; } -#endif /*! @brief remove element from a JSON array given an index @@ -4421,7 +4353,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec @since version 1.0.0 */ - template + template < class KeyT, typename detail::enable_if_t < + detail::is_key_type::value > ... > iterator find(KeyT&& key) { auto result = end(); @@ -4438,7 +4371,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec @brief find an element in a JSON object @copydoc find(KeyT&&) */ - template + template < class KeyT, typename detail::enable_if_t < + detail::is_key_type::value > ... > const_iterator find(KeyT&& key) const { auto result = cend(); @@ -4472,7 +4406,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec @since version 1.0.0 */ - template + template < class KeyT, typename detail::enable_if_t < + detail::is_key_type::value > ... > size_type count(KeyT&& key) const { // return 0 for all nonobject types @@ -4504,9 +4439,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec @since version 3.6.0 */ - template < typename KeyT, typename std::enable_if < - !std::is_same::type, json_pointer>::value, int >::type = 0 > - bool contains(KeyT && key) const + template < class KeyT, typename detail::enable_if_t < + !std::is_same::type, json_pointer>::value&& detail::is_key_type::value > ... > + bool contains(KeyT&& key) const { return is_object() && m_value.object->find(std::forward(key)) != m_value.object->end(); } diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 9c0bc3eea..c7f9e2b46 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -3771,6 +3771,18 @@ struct is_constructible_tuple : std::false_type {}; template struct is_constructible_tuple> : conjunction...> {}; + +/// type to check if KeyType can be used as object key +template +struct is_key_type +{ + static constexpr bool value = +#if defined(JSON_HAS_CPP_17) + std::is_same::type, std::string_view>::value || +#endif + std::is_convertible::value; +}; + } // namespace detail } // namespace nlohmann @@ -20384,12 +20396,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec written using `at()`. It also demonstrates the different exceptions that can be thrown.,at__object_t_key_type} */ - template < class KeyT, typename std::enable_if < - !std::is_same::type, json_pointer>::value&& ( -#if defined(JSON_HAS_CPP_17) - std::is_same::type, std::string_view>::value || -#endif - std::is_convertible::value), int >::type = 0 > + template < class KeyT, typename detail::enable_if_t < + detail::is_key_type::value&& !std::is_same::type, json_pointer>::value > ... > reference at(const KeyT& key) { // at only works for objects @@ -20437,12 +20445,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec `at()`. It also demonstrates the different exceptions that can be thrown., at__object_t_key_type_const} */ - template < class KeyT, typename std::enable_if < - !std::is_same::type, json_pointer>::value&& ( -#if defined(JSON_HAS_CPP_17) - std::is_same::type, std::string_view>::value || -#endif - std::is_convertible::value), int >::type = 0 > + template < class KeyT, typename detail::enable_if_t < + detail::is_key_type::value&& !std::is_same::type, json_pointer>::value > ... > const_reference at(const KeyT& key) const { // at only works for objects @@ -20576,13 +20580,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec @since version 1.0.0; template KeyT added in version 3.10.0 */ - template < class KeyT, typename std::enable_if < - !std::is_same::type, json_pointer>::value&& ( -#if defined(JSON_HAS_CPP_17) - std::is_same::type, std::string_view>::value || -#endif - std::is_convertible::value), int >::type = 0 > - reference operator[](KeyT && key) + template < class KeyT, typename detail::enable_if_t < + detail::is_key_type::value&& !std::is_same::type, json_pointer>::value > ... > + reference operator[](KeyT&& key) { // implicitly convert null value to an empty object if (is_null()) @@ -20639,13 +20639,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec @since version 1.0.0; template KeyT added in version 3.10.0 */ - template < class KeyT, typename std::enable_if < - !std::is_same::type, json_pointer>::value&& ( -#if defined(JSON_HAS_CPP_17) - std::is_same::type, std::string_view>::value || -#endif - std::is_convertible::value), int >::type = 0 > - const_reference operator[](KeyT && key) const + template < class KeyT, typename detail::enable_if_t < + detail::is_key_type::value&& !std::is_same::type, json_pointer>::value > ... > + const_reference operator[](KeyT&& key) const { // operator[] only works for objects if (JSON_HEDLEY_LIKELY(is_object())) @@ -20711,13 +20707,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec @since version 1.0.0, KeyType template added in 3.10.0 */ // using std::is_convertible in a std::enable_if will fail when using explicit conversions - template < class KeyType, class ValueType, typename std::enable_if < + template < class KeyType, class ValueType, typename detail::enable_if_t < detail::is_getable::value - && !std::is_same::value&& ( -#if defined(JSON_HAS_CPP_17) - std::is_same::value || -#endif - std::is_convertible::value), int >::type = 0 > + && !std::is_same::value&& detail::is_key_type::value > ... > ValueType value(const KeyType& key, const ValueType& default_value) const { // at only works for objects @@ -20740,11 +20732,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec @brief overload for a default value of type const char* @copydoc basic_json::value(const typename object_t::key_type&, const ValueType&) const */ - template < class KeyType, typename std::enable_if < -#if defined(JSON_HAS_CPP_17) - std::is_same::value || -#endif - std::is_convertible::value, int >::type = 0 > + template < class KeyType, typename detail::enable_if_t < + detail::is_key_type::value > ... > string_t value(const KeyType& key, const char* default_value) const { return value(key, string_t(default_value)); @@ -21145,7 +21134,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec Removes elements from a JSON object with the key value @a key. @param[in] key value of the elements to remove - @tparam KeyT a type convertible to an object key + @tparam KeyT a type convertible to an object key or a std::string_view @return Number of elements removed. If @a ObjectType is the default `std::map` type, the return value will always be `0` (@a key was not @@ -21169,53 +21158,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec @since version 1.0.0; template added in version 3.10.0 */ - template < class KeyT, typename std::enable_if < -#if defined(JSON_HAS_CPP_17) - !std::is_same::type, std::string_view>::value&& -#endif - std::is_convertible::value, int >::type = 0 > - size_type erase(KeyT && key) - { - // this erase only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - return m_value.object->erase(std::forward(key)); - } - - JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this)); - } - -#if defined(JSON_HAS_CPP_17) - /*! - @brief remove element from a JSON object given a key - - Removes elements from a JSON object with the key value @a key. - - @param[in] key value of the elements to remove - - @return Number of elements removed. If @a ObjectType is the default - `std::map` type, the return value will always be `0` (@a key was not - found) or `1` (@a key was found). - - @post References and iterators to the erased elements are invalidated. - Other references and iterators are not affected. - - @throw type_error.307 when called on a type other than JSON object; - example: `"cannot use erase() with null"` - - @complexity `log(size()) + count(key)` - - @liveexample{The example shows the effect of `erase()`.,erase__key_type} - - @sa see @ref erase(IteratorType) -- removes the element at a given position - @sa see @ref erase(IteratorType, IteratorType) -- removes the elements in - the given range - @sa see @ref erase(const size_type) -- removes the element from an array at - the given index - - @since version 3.10.0 - */ - size_type erase(const std::string_view& key) + template < class KeyT, typename detail::enable_if_t < + detail::is_key_type::value > ... > + size_type erase(KeyT&& key) { // this erase only works for objects if (JSON_HEDLEY_UNLIKELY(!is_object())) @@ -21232,7 +21177,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec return 0; } -#endif /*! @brief remove element from a JSON array given an index @@ -21310,7 +21254,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec @since version 1.0.0 */ - template + template < class KeyT, typename detail::enable_if_t < + detail::is_key_type::value > ... > iterator find(KeyT&& key) { auto result = end(); @@ -21327,7 +21272,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec @brief find an element in a JSON object @copydoc find(KeyT&&) */ - template + template < class KeyT, typename detail::enable_if_t < + detail::is_key_type::value > ... > const_iterator find(KeyT&& key) const { auto result = cend(); @@ -21361,7 +21307,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec @since version 1.0.0 */ - template + template < class KeyT, typename detail::enable_if_t < + detail::is_key_type::value > ... > size_type count(KeyT&& key) const { // return 0 for all nonobject types @@ -21393,9 +21340,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec @since version 3.6.0 */ - template < typename KeyT, typename std::enable_if < - !std::is_same::type, json_pointer>::value, int >::type = 0 > - bool contains(KeyT && key) const + template < class KeyT, typename detail::enable_if_t < + !std::is_same::type, json_pointer>::value&& detail::is_key_type::value > ... > + bool contains(KeyT&& key) const { return is_object() && m_value.object->find(std::forward(key)) != m_value.object->end(); }