-
-
Notifications
You must be signed in to change notification settings - Fork 6.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add transparent comparator and perfect forwarding support to find() and count() #795
Conversation
This avoids unnecessary string copies on often used find().
Copied from solution to nlohmann#464
Found some chat on #464 for similar issues. Hijacked the solution there for this new functionality. |
Can one of the admins verify this patch? |
@trilogy-service-ro Please stop spamming PRs. |
src/json.hpp
Outdated
basic_json>>>; | ||
|
||
using object_comparator_key_t = typename object_t::key_type; | ||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason not to do the transparent comparator across the board for C++14 and higher?
src/json.hpp
Outdated
@@ -10894,9 +10920,9 @@ class basic_json | |||
|
|||
/*! | |||
@brief find an element in a JSON object | |||
@copydoc find(typename object_t::key_type) | |||
@copydoc find(object_transparent_comparator_key_t) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where is this type (with transparent in it) defined? Just a typo here?
src/json.hpp
Outdated
@@ -10929,7 +10955,7 @@ class basic_json | |||
|
|||
@since version 1.0.0 | |||
*/ | |||
size_type count(typename object_t::key_type key) const | |||
size_type count(object_comparator_key_t key) const |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would the find
and count
functions be better as templates with perfect forwarding, so we can find or count directly anything that the underlying object class can find or count?
Instead implement @gregmarr's PR comments that perfect forwarding should be used. Also cleaned up cpp language standard detection.
@gregmarr thanks for the great feedback. I've implemented your suggested changes |
src/json.hpp
Outdated
@@ -110,11 +110,11 @@ SOFTWARE. | |||
#endif | |||
|
|||
// string_view support | |||
#if defined(_MSC_VER) && defined(_HAS_CXX17) && _HAS_CXX17 == 1 | |||
#define JSON_USE_STRING_VIEW | |||
#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_MSC_VER) && _MSC_VER > 1900 && defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we use __has_include
instead?
src/json.hpp
Outdated
@copydoc find(typename object_t::key_type) | ||
*/ | ||
template<typename KeyT> | ||
iterator find(KeyT&& key) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we define those perfect-forwarded overloads for C++11 as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The templated member functions don't exist in 11. They were added in 14.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but we could keep those overloads in C++11, they will call the regular comparators which will perform implicit conversions, as for:
std::cout << std::multiplies<int>{}(2.0f, 2.0f) << std::endl;
I haven't tested my suggestion though, so it might very well be bogus.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My first thought was that it might be weird for users that aren't familiar with the difference in capabilities between std::map
in 11 and 14 to have the templated type that only works with things implicitly convertible to the key type, but maybe that's not an issue, as you'd get the same issue with anything that isn't comparable with the key type with the 14 version. The STL kept the non-template find()
and count()
, but likely only for backwards compat. If it works, I think it would be better with just the templated versions. If we can't eliminate the fixed type versions, we should add const &
to them to match the std::map
versions. Right now we make a copy unnecessarily. (I just noticed this now.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the suggestion, pushed changes to just have perfect-forwarding only
test/CMakeLists.txt
Outdated
if(MSVC_VERSION GREATER_EQUAL 1910) | ||
# 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() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC Appveyor already runs with VS2017, you might want to put that flag in the Appveyor file?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed we have three configurations for AppVeyor:
- MSVC 2015
- MSVC 2017
- MSVC 2017 +
/permissive- /std:c++latest /utf-8
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah nice, didn't realize that thanks. I'll this remove this then.
Sorry - AppVeyor fails because of a recent change of mine. I shall fix this. |
The |
@jseward You're welcome. I'm glad it worked out. |
travis-ci failing with:
don't notice an obvious way to retry |
Travis' support for macOS is a bit flaky. I restarted the job. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me.
Thanks a lot! |
This avoids unnecessary string copies and allocation on often used
find()
ifstd::string_view
is supported.NOTE: currently only implemented for MSVS 2017, should be easily enabled for other compilers as well but don't have them available.