From 33c6511dd0b04337ba4d0abe151ce826372ba551 Mon Sep 17 00:00:00 2001 From: Jamie Seward Date: Mon, 23 Oct 2017 00:43:26 -0700 Subject: [PATCH] Remove JSON_HAS_STRING_VIEW Instead implement @gregmarr's PR comments that perfect forwarding should be used. Also cleaned up cpp language standard detection. --- src/json.hpp | 100 ++++++++++++++++++++++++++++++-------------- test/CMakeLists.txt | 2 +- 2 files changed, 70 insertions(+), 32 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 2e619c85..16b0b1fd 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -109,16 +109,14 @@ SOFTWARE. #define JSON_UNLIKELY(x) x #endif -// string_view support -#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_MSC_VER) && _MSC_VER > 1900 && defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 - #define JSON_HAS_STRING_VIEW +// cpp language standard detection +#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 +#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) + #define JSON_HAS_CPP_14 #endif -#if defined(JSON_HAS_STRING_VIEW) - #include -#endif - - /*! @brief namespace for Niels Lohmann @see https://github.com/nlohmann @@ -7600,26 +7598,18 @@ class basic_json specified "unordered" nature of JSON objects. */ -#if defined(JSON_HAS_STRING_VIEW) - // if std::string_view is to be used the object_t must - // be declared with a transparent comparator - // https://stackoverflow.com/questions/35525777/use-of-string-view-for-map-lookup - using object_t = ObjectType, - AllocatorType>>; - - using object_comparator_key_t = std::string_view; +#if defined(JSON_HAS_CPP_14) + // Use transparent comparator if possible, combined with perfect forwarding + // on find() and count() calls prevents unnecessary string construction. + using object_comparator_t = std::less<>; #else - using object_t = ObjectType, - AllocatorType>>; - - using object_comparator_key_t = typename object_t::key_type; + using object_comparator_t = std::less; #endif + using object_t = ObjectType>>; /*! @brief a type for an array @@ -9868,7 +9858,7 @@ class basic_json #ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015 and not std::is_same>::value #endif -#if defined(JSON_HAS_STRING_VIEW) +#if defined(JSON_HAS_CPP_17) and not std::is_same::value #endif , int >::type = 0 > @@ -10906,7 +10896,7 @@ class basic_json @since version 1.0.0 */ - iterator find(object_comparator_key_t key) + iterator find(typename object_t::key_type key) { auto result = end(); @@ -10920,9 +10910,9 @@ class basic_json /*! @brief find an element in a JSON object - @copydoc find(object_transparent_comparator_key_t) + @copydoc find(typename object_t::key_type) */ - const_iterator find(object_comparator_key_t key) const + const_iterator find(typename object_t::key_type key) const { auto result = cend(); @@ -10934,6 +10924,42 @@ class basic_json return result; } +#ifdef JSON_HAS_CPP_14 + /*! + @brief find an element in a JSON object + @copydoc find(typename object_t::key_type) + */ + template + iterator find(KeyT&& key) + { + auto result = end(); + + if (is_object()) + { + result.m_it.object_iterator = m_value.object->find(std::forward(key)); + } + + return result; + } + + /*! + @brief find an element in a JSON object + @copydoc find(typename object_t::key_type) + */ + template + const_iterator find(KeyT&& key) const + { + auto result = cend(); + + if (is_object()) + { + result.m_it.object_iterator = m_value.object->find(std::forward(key)); + } + + return result; + } +#endif + /*! @brief returns the number of occurrences of a key in a JSON object @@ -10955,12 +10981,24 @@ class basic_json @since version 1.0.0 */ - size_type count(object_comparator_key_t key) const + size_type count(typename object_t::key_type key) const { // return 0 for all nonobject types return is_object() ? m_value.object->count(key) : 0; } +#ifdef JSON_HAS_CPP_14 + /*! + @brief returns the number of occurrences of a key in a JSON object + @copydoc count(typename object_t::key_type) + */ + template + size_type count(KeyT&& key) const + { + // return 0 for all nonobject types + return is_object() ? m_value.object->count(std::forward(key)) : 0; + } +#endif /// @} diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 1c1455a2..2c2c7479 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -82,7 +82,7 @@ if(MSVC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4389 /wd4309 /wd4566 /wd4996") if(MSVC_VERSION GREATER_EQUAL 1910) - # Enable c++17 support in Visual Studio 2017 (for testing string_view support) + # Enable c++17 support in Visual Studio 2017 (for testing perfect forwarding and transparent comparator in find() / count()) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++17") endif() endif()