From ab06fc99513676e55a518c5ef3f06f86ecd550ef Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Thu, 8 Jun 2023 18:46:48 +0200 Subject: [PATCH 1/5] Fix Clang-Tidy warnings (#4047) --- .clang-tidy | 1 + .../nlohmann/detail/iterators/iteration_proxy.hpp | 4 ++-- include/nlohmann/ordered_map.hpp | 10 +++++----- single_include/nlohmann/json.hpp | 14 +++++++------- tests/src/unit-algorithms.cpp | 1 + tests/src/unit-allocator.cpp | 2 +- tests/src/unit-readme.cpp | 4 ++-- tests/src/unit-unicode2.cpp | 2 +- tests/src/unit-unicode3.cpp | 2 +- tests/src/unit-unicode4.cpp | 2 +- tests/src/unit-unicode5.cpp | 2 +- tests/thirdparty/fifo_map/fifo_map.hpp | 2 +- 12 files changed, 24 insertions(+), 22 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index f0bb7b434..1b0fff5ce 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -38,6 +38,7 @@ Checks: '*, -llvmlibc-*, -misc-use-anonymous-namespace, -misc-confusable-identifiers, + -misc-include-cleaner, -misc-no-recursion, -misc-non-private-member-variables-in-classes, -modernize-concat-nested-namespaces, diff --git a/include/nlohmann/detail/iterators/iteration_proxy.hpp b/include/nlohmann/detail/iterators/iteration_proxy.hpp index 61b942000..33bfc36ba 100644 --- a/include/nlohmann/detail/iterators/iteration_proxy.hpp +++ b/include/nlohmann/detail/iterators/iteration_proxy.hpp @@ -69,10 +69,10 @@ template class iteration_proxy_value // older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions iteration_proxy_value(iteration_proxy_value&&) noexcept(std::is_nothrow_move_constructible::value - && std::is_nothrow_move_constructible::value) = default; + && std::is_nothrow_move_constructible::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) iteration_proxy_value& operator=(iteration_proxy_value&&) noexcept(std::is_nothrow_move_assignable::value - && std::is_nothrow_move_assignable::value) = default; + && std::is_nothrow_move_assignable::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) ~iteration_proxy_value() = default; /// dereference operator (needed for range-based for) diff --git a/include/nlohmann/ordered_map.hpp b/include/nlohmann/ordered_map.hpp index 55c630d90..5d28cdf20 100644 --- a/include/nlohmann/ordered_map.hpp +++ b/include/nlohmann/ordered_map.hpp @@ -118,7 +118,7 @@ template , template::value, int> = 0> - T & at(KeyType && key) + T & at(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward) { for (auto it = this->begin(); it != this->end(); ++it) { @@ -146,7 +146,7 @@ template , template::value, int> = 0> - const T & at(KeyType && key) const + const T & at(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward) { for (auto it = this->begin(); it != this->end(); ++it) { @@ -180,7 +180,7 @@ template , template::value, int> = 0> - size_type erase(KeyType && key) + size_type erase(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward) { for (auto it = this->begin(); it != this->end(); ++it) { @@ -271,7 +271,7 @@ template , template::value, int> = 0> - size_type count(KeyType && key) const + size_type count(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward) { for (auto it = this->begin(); it != this->end(); ++it) { @@ -297,7 +297,7 @@ template , template::value, int> = 0> - iterator find(KeyType && key) + iterator find(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward) { for (auto it = this->begin(); it != this->end(); ++it) { diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 443a69fee..ddd3131dc 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -5151,10 +5151,10 @@ template class iteration_proxy_value // older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions iteration_proxy_value(iteration_proxy_value&&) noexcept(std::is_nothrow_move_constructible::value - && std::is_nothrow_move_constructible::value) = default; + && std::is_nothrow_move_constructible::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) iteration_proxy_value& operator=(iteration_proxy_value&&) noexcept(std::is_nothrow_move_assignable::value - && std::is_nothrow_move_assignable::value) = default; + && std::is_nothrow_move_assignable::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) ~iteration_proxy_value() = default; /// dereference operator (needed for range-based for) @@ -19036,7 +19036,7 @@ template , template::value, int> = 0> - T & at(KeyType && key) + T & at(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward) { for (auto it = this->begin(); it != this->end(); ++it) { @@ -19064,7 +19064,7 @@ template , template::value, int> = 0> - const T & at(KeyType && key) const + const T & at(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward) { for (auto it = this->begin(); it != this->end(); ++it) { @@ -19098,7 +19098,7 @@ template , template::value, int> = 0> - size_type erase(KeyType && key) + size_type erase(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward) { for (auto it = this->begin(); it != this->end(); ++it) { @@ -19189,7 +19189,7 @@ template , template::value, int> = 0> - size_type count(KeyType && key) const + size_type count(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward) { for (auto it = this->begin(); it != this->end(); ++it) { @@ -19215,7 +19215,7 @@ template , template::value, int> = 0> - iterator find(KeyType && key) + iterator find(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward) { for (auto it = this->begin(); it != this->end(); ++it) { diff --git a/tests/src/unit-algorithms.cpp b/tests/src/unit-algorithms.cpp index f4b87f8fa..d5a997075 100644 --- a/tests/src/unit-algorithms.cpp +++ b/tests/src/unit-algorithms.cpp @@ -8,6 +8,7 @@ #include "doctest_compatibility.h" +#include #include using nlohmann::json; diff --git a/tests/src/unit-allocator.cpp b/tests/src/unit-allocator.cpp index f2e63552a..f9a25b24f 100644 --- a/tests/src/unit-allocator.cpp +++ b/tests/src/unit-allocator.cpp @@ -24,7 +24,7 @@ struct bad_allocator : std::allocator template bad_allocator(const bad_allocator& /*unused*/) { } template - void construct(T* /*unused*/, Args&& ... /*unused*/) + void construct(T* /*unused*/, Args&& ... /*unused*/) // NOLINT(cppcoreguidelines-missing-std-forward) { throw std::bad_alloc(); } diff --git a/tests/src/unit-readme.cpp b/tests/src/unit-readme.cpp index 504466d66..9ed343531 100644 --- a/tests/src/unit-readme.cpp +++ b/tests/src/unit-readme.cpp @@ -119,13 +119,13 @@ TEST_CASE("README" * doctest::skip()) // serialization with pretty printing // pass in the amount of spaces to indent - std::cout << j.dump(4) << std::endl; + std::cout << j.dump(4) << std::endl; // NOLINT(performance-avoid-endl) // { // "happy": true, // "pi": 3.141 // } - std::cout << std::setw(2) << j << std::endl; + std::cout << std::setw(2) << j << std::endl; // NOLINT(performance-avoid-endl) } { diff --git a/tests/src/unit-unicode2.cpp b/tests/src/unit-unicode2.cpp index 02eab6f95..290bbff94 100644 --- a/tests/src/unit-unicode2.cpp +++ b/tests/src/unit-unicode2.cpp @@ -123,7 +123,7 @@ void check_utf8string(bool success_expected, int byte1, int byte2 = -1, int byte { if (++calls % 100000 == 0) { - std::cout << calls << " of 455355 UTF-8 strings checked" << std::endl; + std::cout << calls << " of 455355 UTF-8 strings checked" << std::endl; // NOLINT(performance-avoid-endl) } static std::string json_string; diff --git a/tests/src/unit-unicode3.cpp b/tests/src/unit-unicode3.cpp index 80cff40ad..396081108 100644 --- a/tests/src/unit-unicode3.cpp +++ b/tests/src/unit-unicode3.cpp @@ -123,7 +123,7 @@ void check_utf8string(bool success_expected, int byte1, int byte2 = -1, int byte { if (++calls % 100000 == 0) { - std::cout << calls << " of 1641521 UTF-8 strings checked" << std::endl; + std::cout << calls << " of 1641521 UTF-8 strings checked" << std::endl; // NOLINT(performance-avoid-endl) } static std::string json_string; diff --git a/tests/src/unit-unicode4.cpp b/tests/src/unit-unicode4.cpp index 6992b3123..966a241e0 100644 --- a/tests/src/unit-unicode4.cpp +++ b/tests/src/unit-unicode4.cpp @@ -123,7 +123,7 @@ void check_utf8string(bool success_expected, int byte1, int byte2 = -1, int byte { if (++calls % 100000 == 0) { - std::cout << calls << " of 5517507 UTF-8 strings checked" << std::endl; + std::cout << calls << " of 5517507 UTF-8 strings checked" << std::endl; // NOLINT(performance-avoid-endl) } static std::string json_string; diff --git a/tests/src/unit-unicode5.cpp b/tests/src/unit-unicode5.cpp index be12f3ae3..c75f76701 100644 --- a/tests/src/unit-unicode5.cpp +++ b/tests/src/unit-unicode5.cpp @@ -123,7 +123,7 @@ void check_utf8string(bool success_expected, int byte1, int byte2 = -1, int byte { if (++calls % 100000 == 0) { - std::cout << calls << " of 1246225 UTF-8 strings checked" << std::endl; + std::cout << calls << " of 1246225 UTF-8 strings checked" << std::endl; // NOLINT(performance-avoid-endl) } static std::string json_string; diff --git a/tests/thirdparty/fifo_map/fifo_map.hpp b/tests/thirdparty/fifo_map/fifo_map.hpp index ea1ce084f..180d1768b 100644 --- a/tests/thirdparty/fifo_map/fifo_map.hpp +++ b/tests/thirdparty/fifo_map/fifo_map.hpp @@ -300,7 +300,7 @@ template < /// insert value template - std::pair insert( P&& value ) + std::pair insert( P&& value ) // NOLINT(cppcoreguidelines-missing-std-forward) { m_compare.add_key(value.first); return m_map.insert(value); From 254395e5f7731b5595e7c11ac4b929c923582114 Mon Sep 17 00:00:00 2001 From: gregmarr Date: Thu, 8 Jun 2023 09:47:44 -0700 Subject: [PATCH 2/5] Add to CONTRIBUTING.md that `make pretty` is required for test updates. (#4045) --- .github/CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 4b6b4aea3..4d33c67bf 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -32,7 +32,7 @@ To make changes, you need to edit the following files: 1. [`include/nlohmann/*`](https://github.com/nlohmann/json/tree/develop/include/nlohmann) - These files are the sources of the library. Before testing or creating a pull request, execute `make amalgamate` to regenerate `single_include/nlohmann/json.hpp` and `single_include/nlohmann/json_fwd.hpp`. -2. [`tests/src/unit-*.cpp`](https://github.com/nlohmann/json/tree/develop/tests/src) - These files contain the [doctest](https://github.com/onqtam/doctest) unit tests which currently cover [100 %](https://coveralls.io/github/nlohmann/json) of the library's code. +2. [`tests/src/unit-*.cpp`](https://github.com/nlohmann/json/tree/develop/tests/src) - These files contain the [doctest](https://github.com/onqtam/doctest) unit tests which currently cover [100 %](https://coveralls.io/github/nlohmann/json) of the library's code. Before creating a pull request, execute `make pretty` to make sure that the style is correct, as this will be checked by the CI. If you add or change a feature, please also add a unit test to this file. The unit tests can be compiled and executed with From 793878898fa5e800c1337ebc56330d29a2412b45 Mon Sep 17 00:00:00 2001 From: Tomerkm Date: Sun, 11 Jun 2023 10:59:57 +0300 Subject: [PATCH 3/5] Added to tests the file unit-algorithm.cpp (c++ 11) functions from algorithm library (#4044) --- tests/src/unit-algorithms.cpp | 71 +++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/tests/src/unit-algorithms.cpp b/tests/src/unit-algorithms.cpp index d5a997075..3ecaacde4 100644 --- a/tests/src/unit-algorithms.cpp +++ b/tests/src/unit-algorithms.cpp @@ -295,4 +295,75 @@ TEST_CASE("algorithms") std::sort_heap(j_array.begin(), j_array.end()); CHECK(j_array == json({false, true, 3, 13, 29, {{"one", 1}, {"two", 2}}, {1, 2, 3}, "baz", "foo"})); } + + SECTION("iota") + { + SECTION("int") + { + json json_arr = {0, 5, 2, 4, 10, 20, 30, 40, 50, 1}; + std::iota(json_arr.begin(), json_arr.end(), 0); + CHECK(json_arr == json({0, 1, 2, 3, 4, 5, 6, 7, 8, 9})); + } + SECTION("double") + { + json json_arr = {0.5, 1.5, 1.3, 4.1, 10.2, 20.5, 30.6, 40.1, 50.22, 1.5}; + std::iota(json_arr.begin(), json_arr.end(), 0.5); + CHECK(json_arr == json({0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5})); + } + + SECTION("char") + { + json json_arr = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', '0', '1'}; + std::iota(json_arr.begin(), json_arr.end(), '0'); + CHECK(json_arr == json({'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'})); + } + } + + + SECTION("copy") + { + SECTION("copy without if") + { + json dest_arr; + const json source_arr = {1, 2, 3, 4}; + + std::copy(source_arr.begin(), source_arr.end(), std::back_inserter(dest_arr)); + + CHECK(dest_arr == source_arr); + } + SECTION("copy if") + { + json dest_arr; + const json source_arr = {0, 3, 6, 9, 12, 15, 20}; + + + std::copy_if(source_arr.begin(), source_arr.end(), std::back_inserter(dest_arr), [](const json & _value) + { + return _value.get() % 3 == 0; + }); + CHECK(dest_arr == json({0, 3, 6, 9, 12, 15})); + } + SECTION("copy n") + { + const json source_arr = {0, 1, 2, 3, 4, 5, 6, 7}; + json dest_arr; + const unsigned char numToCopy = 2; + + std::copy_n(source_arr.begin(), numToCopy, std::back_inserter(dest_arr)); + CHECK(dest_arr == json{0, 1}); + + } + SECTION("copy n chars") + { + const json source_arr = {'1', '2', '3', '4', '5', '6', '7'}; + json dest_arr; + const unsigned char numToCopy = 4; + + std::copy_n(source_arr.begin(), numToCopy, std::back_inserter(dest_arr)); + CHECK(dest_arr == json{'1', '2', '3', '4'}); + } + } + + + } From c71ecde505ebf236048a731c81ae8ecaf2b260a8 Mon Sep 17 00:00:00 2001 From: No Date: Sun, 11 Jun 2023 04:06:24 -0400 Subject: [PATCH 4/5] Use template get instead of get in examples (#4039) Co-authored-by: tusooa --- README.md | 36 +++++++++---------- .../from_json__default_constructible.cpp | 2 +- .../from_json__non_default_constructible.cpp | 2 +- docs/examples/get__PointerType.cpp | 10 +++--- docs/examples/get__ValueType_const.cpp | 16 ++++----- ...lohmann_define_type_intrusive_explicit.cpp | 4 +-- .../nlohmann_define_type_intrusive_macro.cpp | 4 +-- ...e_type_intrusive_with_default_explicit.cpp | 4 +-- ...fine_type_intrusive_with_default_macro.cpp | 4 +-- ...ann_define_type_non_intrusive_explicit.cpp | 4 +-- ...ohmann_define_type_non_intrusive_macro.cpp | 4 +-- ...pe_non_intrusive_with_default_explicit.cpp | 4 +-- ..._type_non_intrusive_with_default_macro.cpp | 4 +-- .../examples/nlohmann_json_serialize_enum.cpp | 8 ++--- .../nlohmann_json_serialize_enum_2.cpp | 4 +-- .../docs/api/adl_serializer/from_json.md | 2 +- .../macros/json_disable_enum_serialization.md | 10 +++--- .../macros/json_use_implicit_conversions.md | 2 +- .../macros/nlohmann_json_serialize_enum.md | 2 +- docs/mkdocs/docs/features/arbitrary_types.md | 18 +++++----- docs/mkdocs/docs/features/enum_conversion.md | 6 ++-- .../docs/features/types/number_handling.md | 8 ++--- .../docs/integration/migration_guide.md | 2 +- 23 files changed, 80 insertions(+), 80 deletions(-) diff --git a/README.md b/README.md index acc16eace..ae2a4ad12 100644 --- a/README.md +++ b/README.md @@ -301,7 +301,7 @@ Note the difference between serialization and assignment: json j_string = "this is a string"; // retrieve the string value -auto cpp_string = j_string.get(); +auto cpp_string = j_string.template get(); // retrieve the string value (alternative when a variable already exists) std::string cpp_string2; j_string.get_to(cpp_string2); @@ -310,7 +310,7 @@ j_string.get_to(cpp_string2); std::string serialized_string = j_string.dump(); // output of original string -std::cout << cpp_string << " == " << cpp_string2 << " == " << j_string.get() << '\n'; +std::cout << cpp_string << " == " << cpp_string2 << " == " << j_string.template get() << '\n'; // output of serialized value std::cout << j_string << " == " << serialized_string << std::endl; ``` @@ -483,7 +483,7 @@ for (auto& element : j) { } // getter/setter -const auto tmp = j[0].get(); +const auto tmp = j[0].template get(); j[1] = 42; bool foo = j.at(2); @@ -691,7 +691,7 @@ You can switch off implicit conversions by defining `JSON_USE_IMPLICIT_CONVERSIO // strings std::string s1 = "Hello, world!"; json js = s1; -auto s2 = js.get(); +auto s2 = js.template get(); // NOT RECOMMENDED std::string s3 = js; std::string s4; @@ -700,7 +700,7 @@ s4 = js; // Booleans bool b1 = true; json jb = b1; -auto b2 = jb.get(); +auto b2 = jb.template get(); // NOT RECOMMENDED bool b3 = jb; bool b4; @@ -709,7 +709,7 @@ b4 = jb; // numbers int i = 42; json jn = i; -auto f = jn.get(); +auto f = jn.template get(); // NOT RECOMMENDED double f2 = jb; double f3; @@ -752,9 +752,9 @@ j["age"] = p.age; // convert from JSON: copy each value from the JSON object ns::person p { - j["name"].get(), - j["address"].get(), - j["age"].get() + j["name"].template get(), + j["address"].template get(), + j["age"].template get() }; ``` @@ -771,7 +771,7 @@ std::cout << j << std::endl; // {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"} // conversion: json -> person -auto p2 = j.get(); +auto p2 = j.template get(); // that's it assert(p == p2); @@ -798,13 +798,13 @@ namespace ns { ``` That's all! When calling the `json` constructor with your type, your custom `to_json` method will be automatically called. -Likewise, when calling `get()` or `get_to(your_type&)`, the `from_json` method will be called. +Likewise, when calling `template get()` or `get_to(your_type&)`, the `from_json` method will be called. Some important things: * Those methods **MUST** be in your type's namespace (which can be the global namespace), or the library will not be able to locate them (in this example, they are in namespace `ns`, where `person` is defined). * Those methods **MUST** be available (e.g., proper headers must be included) everywhere you use these conversions. Look at [issue 1108](https://github.com/nlohmann/json/issues/1108) for errors that may occur otherwise. -* When using `get()`, `your_type` **MUST** be [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). (There is a way to bypass this requirement described later.) +* When using `template get()`, `your_type` **MUST** be [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). (There is a way to bypass this requirement described later.) * In function `from_json`, use function [`at()`](https://json.nlohmann.me/api/basic_json/at/) to access the object values rather than `operator[]`. In case a key does not exist, `at` throws an exception that you can handle, whereas `operator[]` exhibits undefined behavior. * You do not need to add serializers or deserializers for STL types like `std::vector`: the library already implements these. @@ -889,8 +889,8 @@ namespace nlohmann { if (j.is_null()) { opt = boost::none; } else { - opt = j.get(); // same as above, but with - // adl_serializer::from_json + opt = j.template get(); // same as above, but with + // adl_serializer::from_json } } }; @@ -917,7 +917,7 @@ namespace nlohmann { // note: the return type is no longer 'void', and the method only takes // one argument static move_only_type from_json(const json& j) { - return {j.get()}; + return {j.template get()}; } // Here's the catch! You must provide a to_json method! Otherwise, you @@ -1021,11 +1021,11 @@ assert(j == "stopped"); // json string to enum json j3 = "running"; -assert(j3.get() == TS_RUNNING); +assert(j3.template get() == TS_RUNNING); // undefined json value to enum (where the first map entry above is the default) json jPi = 3.14; -assert(jPi.get() == TS_INVALID ); +assert(jPi.template get() == TS_INVALID ); ``` Just as in [Arbitrary Type Conversions](#arbitrary-types-conversions) above, @@ -1033,7 +1033,7 @@ Just as in [Arbitrary Type Conversions](#arbitrary-types-conversions) above, - It MUST be available (e.g., proper headers must be included) everywhere you use the conversions. Other Important points: -- When using `get()`, undefined JSON values will default to the first pair specified in your map. Select this default pair carefully. +- When using `template get()`, undefined JSON values will default to the first pair specified in your map. Select this default pair carefully. - If an enum or JSON value is specified more than once in your map, the first matching occurrence from the top of the map will be returned when converting to or from JSON. ### Binary formats (BSON, CBOR, MessagePack, UBJSON, and BJData) diff --git a/docs/examples/from_json__default_constructible.cpp b/docs/examples/from_json__default_constructible.cpp index 17c0551c8..07d71ac95 100644 --- a/docs/examples/from_json__default_constructible.cpp +++ b/docs/examples/from_json__default_constructible.cpp @@ -31,7 +31,7 @@ int main() j["address"] = "744 Evergreen Terrace"; j["age"] = 60; - auto p = j.get(); + auto p = j.template get(); std::cout << p.name << " (" << p.age << ") lives in " << p.address << std::endl; } diff --git a/docs/examples/from_json__non_default_constructible.cpp b/docs/examples/from_json__non_default_constructible.cpp index 6cb86153c..ec8206ead 100644 --- a/docs/examples/from_json__non_default_constructible.cpp +++ b/docs/examples/from_json__non_default_constructible.cpp @@ -47,7 +47,7 @@ int main() j["address"] = "744 Evergreen Terrace"; j["age"] = 60; - auto p = j.get(); + auto p = j.template get(); std::cout << p.name << " (" << p.age << ") lives in " << p.address << std::endl; } diff --git a/docs/examples/get__PointerType.cpp b/docs/examples/get__PointerType.cpp index 2f32ed7af..309c8deeb 100644 --- a/docs/examples/get__PointerType.cpp +++ b/docs/examples/get__PointerType.cpp @@ -9,11 +9,11 @@ int main() json value = 17; // explicitly getting pointers - auto p1 = value.get(); - auto p2 = value.get(); - auto p3 = value.get(); - auto p4 = value.get(); - auto p5 = value.get(); + auto p1 = value.template get(); + auto p2 = value.template get(); + auto p3 = value.template get(); + auto p4 = value.template get(); + auto p5 = value.template get(); // print the pointees std::cout << *p1 << ' ' << *p2 << ' ' << *p3 << ' ' << *p4 << '\n'; diff --git a/docs/examples/get__ValueType_const.cpp b/docs/examples/get__ValueType_const.cpp index 7a703aaeb..db63791fc 100644 --- a/docs/examples/get__ValueType_const.cpp +++ b/docs/examples/get__ValueType_const.cpp @@ -22,14 +22,14 @@ int main() }; // use explicit conversions - auto v1 = json_types["boolean"].get(); - auto v2 = json_types["number"]["integer"].get(); - auto v3 = json_types["number"]["integer"].get(); - auto v4 = json_types["number"]["floating-point"].get(); - auto v5 = json_types["number"]["floating-point"].get(); - auto v6 = json_types["string"].get(); - auto v7 = json_types["array"].get>(); - auto v8 = json_types.get>(); + auto v1 = json_types["boolean"].template get(); + auto v2 = json_types["number"]["integer"].template get(); + auto v3 = json_types["number"]["integer"].template get(); + auto v4 = json_types["number"]["floating-point"].template get(); + auto v5 = json_types["number"]["floating-point"].template get(); + auto v6 = json_types["string"].template get(); + auto v7 = json_types["array"].template get>(); + auto v8 = json_types.template get>(); // print the conversion results std::cout << v1 << '\n'; diff --git a/docs/examples/nlohmann_define_type_intrusive_explicit.cpp b/docs/examples/nlohmann_define_type_intrusive_explicit.cpp index 7d2ba8aa1..f2d6812cb 100644 --- a/docs/examples/nlohmann_define_type_intrusive_explicit.cpp +++ b/docs/examples/nlohmann_define_type_intrusive_explicit.cpp @@ -45,13 +45,13 @@ int main() // deserialization: json -> person json j2 = R"({"address": "742 Evergreen Terrace", "age": 40, "name": "Homer Simpson"})"_json; - auto p2 = j2.get(); + auto p2 = j2.template get(); // incomplete deserialization: json j3 = R"({"address": "742 Evergreen Terrace", "name": "Maggie Simpson"})"_json; try { - auto p3 = j3.get(); + auto p3 = j3.template get(); } catch (json::exception& e) { diff --git a/docs/examples/nlohmann_define_type_intrusive_macro.cpp b/docs/examples/nlohmann_define_type_intrusive_macro.cpp index 2977cd456..9c020689b 100644 --- a/docs/examples/nlohmann_define_type_intrusive_macro.cpp +++ b/docs/examples/nlohmann_define_type_intrusive_macro.cpp @@ -33,13 +33,13 @@ int main() // deserialization: json -> person json j2 = R"({"address": "742 Evergreen Terrace", "age": 40, "name": "Homer Simpson"})"_json; - auto p2 = j2.get(); + auto p2 = j2.template get(); // incomplete deserialization: json j3 = R"({"address": "742 Evergreen Terrace", "name": "Maggie Simpson"})"_json; try { - auto p3 = j3.get(); + auto p3 = j3.template get(); } catch (json::exception& e) { diff --git a/docs/examples/nlohmann_define_type_intrusive_with_default_explicit.cpp b/docs/examples/nlohmann_define_type_intrusive_with_default_explicit.cpp index 7400c47a8..0fb2e1cb2 100644 --- a/docs/examples/nlohmann_define_type_intrusive_with_default_explicit.cpp +++ b/docs/examples/nlohmann_define_type_intrusive_with_default_explicit.cpp @@ -46,10 +46,10 @@ int main() // deserialization: json -> person json j2 = R"({"address": "742 Evergreen Terrace", "age": 40, "name": "Homer Simpson"})"_json; - auto p2 = j2.get(); + auto p2 = j2.template get(); // incomplete deserialization: json j3 = R"({"address": "742 Evergreen Terrace", "name": "Maggie Simpson"})"_json; - auto p3 = j3.get(); + auto p3 = j3.template get(); std::cout << "roundtrip: " << json(p3) << std::endl; } diff --git a/docs/examples/nlohmann_define_type_intrusive_with_default_macro.cpp b/docs/examples/nlohmann_define_type_intrusive_with_default_macro.cpp index 851a3582f..52668516b 100644 --- a/docs/examples/nlohmann_define_type_intrusive_with_default_macro.cpp +++ b/docs/examples/nlohmann_define_type_intrusive_with_default_macro.cpp @@ -33,10 +33,10 @@ int main() // deserialization: json -> person json j2 = R"({"address": "742 Evergreen Terrace", "age": 40, "name": "Homer Simpson"})"_json; - auto p2 = j2.get(); + auto p2 = j2.template get(); // incomplete deserialization: json j3 = R"({"address": "742 Evergreen Terrace", "name": "Maggie Simpson"})"_json; - auto p3 = j3.get(); + auto p3 = j3.template get(); std::cout << "roundtrip: " << json(p3) << std::endl; } diff --git a/docs/examples/nlohmann_define_type_non_intrusive_explicit.cpp b/docs/examples/nlohmann_define_type_non_intrusive_explicit.cpp index b71613d4f..b3040adc6 100644 --- a/docs/examples/nlohmann_define_type_non_intrusive_explicit.cpp +++ b/docs/examples/nlohmann_define_type_non_intrusive_explicit.cpp @@ -38,13 +38,13 @@ int main() // deserialization: json -> person json j2 = R"({"address": "742 Evergreen Terrace", "age": 40, "name": "Homer Simpson"})"_json; - auto p2 = j2.get(); + auto p2 = j2.template get(); // incomplete deserialization: json j3 = R"({"address": "742 Evergreen Terrace", "name": "Maggie Simpson"})"_json; try { - auto p3 = j3.get(); + auto p3 = j3.template get(); } catch (json::exception& e) { diff --git a/docs/examples/nlohmann_define_type_non_intrusive_macro.cpp b/docs/examples/nlohmann_define_type_non_intrusive_macro.cpp index be11a4576..2c76830d8 100644 --- a/docs/examples/nlohmann_define_type_non_intrusive_macro.cpp +++ b/docs/examples/nlohmann_define_type_non_intrusive_macro.cpp @@ -26,13 +26,13 @@ int main() // deserialization: json -> person json j2 = R"({"address": "742 Evergreen Terrace", "age": 40, "name": "Homer Simpson"})"_json; - auto p2 = j2.get(); + auto p2 = j2.template get(); // incomplete deserialization: json j3 = R"({"address": "742 Evergreen Terrace", "name": "Maggie Simpson"})"_json; try { - auto p3 = j3.get(); + auto p3 = j3.template get(); } catch (json::exception& e) { diff --git a/docs/examples/nlohmann_define_type_non_intrusive_with_default_explicit.cpp b/docs/examples/nlohmann_define_type_non_intrusive_with_default_explicit.cpp index 6b538d18d..855ab52b8 100644 --- a/docs/examples/nlohmann_define_type_non_intrusive_with_default_explicit.cpp +++ b/docs/examples/nlohmann_define_type_non_intrusive_with_default_explicit.cpp @@ -44,10 +44,10 @@ int main() // deserialization: json -> person json j2 = R"({"address": "742 Evergreen Terrace", "age": 40, "name": "Homer Simpson"})"_json; - auto p2 = j2.get(); + auto p2 = j2.template get(); // incomplete deserialization: json j3 = R"({"address": "742 Evergreen Terrace", "name": "Maggie Simpson"})"_json; - auto p3 = j3.get(); + auto p3 = j3.template get(); std::cout << "roundtrip: " << json(p3) << std::endl; } diff --git a/docs/examples/nlohmann_define_type_non_intrusive_with_default_macro.cpp b/docs/examples/nlohmann_define_type_non_intrusive_with_default_macro.cpp index aa9bc53b4..8c41c65ec 100644 --- a/docs/examples/nlohmann_define_type_non_intrusive_with_default_macro.cpp +++ b/docs/examples/nlohmann_define_type_non_intrusive_with_default_macro.cpp @@ -31,10 +31,10 @@ int main() // deserialization: json -> person json j2 = R"({"address": "742 Evergreen Terrace", "age": 40, "name": "Homer Simpson"})"_json; - auto p2 = j2.get(); + auto p2 = j2.template get(); // incomplete deserialization: json j3 = R"({"address": "742 Evergreen Terrace", "name": "Maggie Simpson"})"_json; - auto p3 = j3.get(); + auto p3 = j3.template get(); std::cout << "roundtrip: " << json(p3) << std::endl; } diff --git a/docs/examples/nlohmann_json_serialize_enum.cpp b/docs/examples/nlohmann_json_serialize_enum.cpp index f9e472c64..a40db49ea 100644 --- a/docs/examples/nlohmann_json_serialize_enum.cpp +++ b/docs/examples/nlohmann_json_serialize_enum.cpp @@ -44,16 +44,16 @@ int main() // deserialization json j_running = "running"; json j_blue = "blue"; - auto running = j_running.get(); - auto blue = j_blue.get(); + auto running = j_running.template get(); + auto blue = j_blue.template get(); std::cout << j_running << " -> " << running << ", " << j_blue << " -> " << static_cast(blue) << std::endl; // deserializing undefined JSON value to enum // (where the first map entry above is the default) json j_pi = 3.14; - auto invalid = j_pi.get(); - auto unknown = j_pi.get(); + auto invalid = j_pi.template get(); + auto unknown = j_pi.template get(); std::cout << j_pi << " -> " << invalid << ", " << j_pi << " -> " << static_cast(unknown) << std::endl; } diff --git a/docs/examples/nlohmann_json_serialize_enum_2.cpp b/docs/examples/nlohmann_json_serialize_enum_2.cpp index fd27226ca..b35e94cc5 100644 --- a/docs/examples/nlohmann_json_serialize_enum_2.cpp +++ b/docs/examples/nlohmann_json_serialize_enum_2.cpp @@ -26,8 +26,8 @@ int main() // deserialization json j_rot = "rot"; - auto rot = j_rot.get(); - auto red = j_red.get(); + auto rot = j_rot.template get(); + auto red = j_red.template get(); std::cout << j_rot << " -> " << static_cast(rot) << std::endl; std::cout << j_red << " -> " << static_cast(red) << std::endl; } diff --git a/docs/mkdocs/docs/api/adl_serializer/from_json.md b/docs/mkdocs/docs/api/adl_serializer/from_json.md index ba932e9e7..fa19c96f2 100644 --- a/docs/mkdocs/docs/api/adl_serializer/from_json.md +++ b/docs/mkdocs/docs/api/adl_serializer/from_json.md @@ -37,7 +37,7 @@ Copy of the JSON value, converted to `ValueType` ??? example "Example: (1) Default-constructible type" The example below shows how a `from_json` function can be implemented for a user-defined type. This function is - called by the `adl_serializer` when `get()` is called. + called by the `adl_serializer` when `template get()` is called. ```cpp --8<-- "examples/from_json__default_constructible.cpp" diff --git a/docs/mkdocs/docs/api/macros/json_disable_enum_serialization.md b/docs/mkdocs/docs/api/macros/json_disable_enum_serialization.md index 6df3dd5cb..6440e34e3 100644 --- a/docs/mkdocs/docs/api/macros/json_disable_enum_serialization.md +++ b/docs/mkdocs/docs/api/macros/json_disable_enum_serialization.md @@ -53,7 +53,7 @@ The default value is `0`. const json j = Choice::first; // normally invokes from_json parse function but with JSON_DISABLE_ENUM_SERIALIZATION defined, it does not - Choice ch = j.get(); + Choice ch = j.template get(); } ``` @@ -86,7 +86,7 @@ The default value is `0`. const json j = Choice::first; // uses user-defined from_json function defined by macro - Choice ch = j.get(); + Choice ch = j.template get(); } ``` @@ -109,7 +109,7 @@ The default value is `0`. void from_json(const json& j, Choice& ch) { - auto value = j.get(); + auto value = j.template get(); if (value == "first") { ch = Choice::first; @@ -122,7 +122,7 @@ The default value is `0`. void to_json(json& j, const Choice& ch) { - auto value = j.get(); + auto value = j.template get(); if (value == "first") { ch = Choice::first; @@ -139,7 +139,7 @@ The default value is `0`. const json j = Choice::first; // uses user-defined from_json function - Choice ch = j.get(); + Choice ch = j.template get(); } ``` diff --git a/docs/mkdocs/docs/api/macros/json_use_implicit_conversions.md b/docs/mkdocs/docs/api/macros/json_use_implicit_conversions.md index adadffab6..557dfa299 100644 --- a/docs/mkdocs/docs/api/macros/json_use_implicit_conversions.md +++ b/docs/mkdocs/docs/api/macros/json_use_implicit_conversions.md @@ -46,7 +46,7 @@ By default, implicit conversions are enabled. ```cpp json j = "Hello, world!"; - auto s = j.get(); + auto s = j.template get(); ``` ## See also diff --git a/docs/mkdocs/docs/api/macros/nlohmann_json_serialize_enum.md b/docs/mkdocs/docs/api/macros/nlohmann_json_serialize_enum.md index c28765a8c..dc2cc8ecb 100644 --- a/docs/mkdocs/docs/api/macros/nlohmann_json_serialize_enum.md +++ b/docs/mkdocs/docs/api/macros/nlohmann_json_serialize_enum.md @@ -37,7 +37,7 @@ inline void from_json(const BasicJsonType& j, type& e); !!! important "Important notes" - - When using [`get()`](../basic_json/get.md), undefined JSON values will default to the first specified + - When using [`template get()`](../basic_json/get.md), undefined JSON values will default to the first specified conversion. Select this default pair carefully. See example 1 below. - If an enum or JSON value is specified in multiple conversions, the first matching conversion from the top of the list will be returned when converting to or from JSON. See example 2 below. diff --git a/docs/mkdocs/docs/features/arbitrary_types.md b/docs/mkdocs/docs/features/arbitrary_types.md index 046a597a3..9b54fcb3e 100644 --- a/docs/mkdocs/docs/features/arbitrary_types.md +++ b/docs/mkdocs/docs/features/arbitrary_types.md @@ -24,9 +24,9 @@ j["age"] = p.age; // convert from JSON: copy each value from the JSON object ns::person p { - j["name"].get(), - j["address"].get(), - j["age"].get() + j["name"].template get(), + j["address"].template get(), + j["age"].template get() }; ``` @@ -43,7 +43,7 @@ std::cout << j << std::endl; // {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"} // conversion: json -> person -auto p2 = j.get(); +auto p2 = j.template get(); // that's it assert(p == p2); @@ -70,13 +70,13 @@ namespace ns { ``` That's all! When calling the `json` constructor with your type, your custom `to_json` method will be automatically called. -Likewise, when calling `get()` or `get_to(your_type&)`, the `from_json` method will be called. +Likewise, when calling `template get()` or `get_to(your_type&)`, the `from_json` method will be called. Some important things: * Those methods **MUST** be in your type's namespace (which can be the global namespace), or the library will not be able to locate them (in this example, they are in namespace `ns`, where `person` is defined). * Those methods **MUST** be available (e.g., proper headers must be included) everywhere you use these conversions. Look at [issue 1108](https://github.com/nlohmann/json/issues/1108) for errors that may occur otherwise. -* When using `get()`, `your_type` **MUST** be [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). (There is a way to bypass this requirement described later.) +* When using `template get()`, `your_type` **MUST** be [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). (There is a way to bypass this requirement described later.) * In function `from_json`, use function [`at()`](../api/basic_json/at.md) to access the object values rather than `operator[]`. In case a key does not exist, `at` throws an exception that you can handle, whereas `operator[]` exhibits undefined behavior. * You do not need to add serializers or deserializers for STL types like `std::vector`: the library already implements these. @@ -171,7 +171,7 @@ struct adl_serializer> { if (j.is_null()) { opt = boost::none; } else { - opt = j.get(); // same as above, but with + opt = j.template get(); // same as above, but with // adl_serializer::from_json } } @@ -204,7 +204,7 @@ namespace nlohmann { // note: the return type is no longer 'void', and the method only takes // one argument static move_only_type from_json(const json& j) { - return {j.get()}; + return {j.template get()}; } // Here's the catch! You must provide a to_json method! Otherwise, you @@ -268,7 +268,7 @@ struct bad_serializer static void to_json(const BasicJsonType& j, T& value) { // this calls BasicJsonType::json_serializer::from_json(j, value); // if BasicJsonType::json_serializer == bad_serializer ... oops! - value = j.template get(); // oops! + value = j.template template get(); // oops! } }; ``` diff --git a/docs/mkdocs/docs/features/enum_conversion.md b/docs/mkdocs/docs/features/enum_conversion.md index 59ffbd5f1..1755bca2a 100644 --- a/docs/mkdocs/docs/features/enum_conversion.md +++ b/docs/mkdocs/docs/features/enum_conversion.md @@ -36,11 +36,11 @@ assert(j == "stopped"); // json string to enum json j3 = "running"; -assert(j3.get() == TS_RUNNING); +assert(j3.template get() == TS_RUNNING); // undefined json value to enum (where the first map entry above is the default) json jPi = 3.14; -assert(jPi.get() == TS_INVALID ); +assert(jPi.template get() == TS_INVALID ); ``` ## Notes @@ -54,7 +54,7 @@ Just as in [Arbitrary Type Conversions](arbitrary_types.md) above, Other Important points: -- When using `get()`, undefined JSON values will default to the first pair specified in your map. Select this +- When using `template get()`, undefined JSON values will default to the first pair specified in your map. Select this default pair carefully. - If an enum or JSON value is specified more than once in your map, the first matching occurrence from the top of the map will be returned when converting to or from JSON. diff --git a/docs/mkdocs/docs/features/types/number_handling.md b/docs/mkdocs/docs/features/types/number_handling.md index 03d8c9c69..c457ae07c 100644 --- a/docs/mkdocs/docs/features/types/number_handling.md +++ b/docs/mkdocs/docs/features/types/number_handling.md @@ -235,9 +235,9 @@ integers, and between integers and floating-point values to integers. This beha !!! warning "Unconditional number conversions" ```cpp hl_lines="3" - double d = 42.3; // non-integer double value 42.3 - json jd = d; // stores double value 42.3 - std::int64_t i = jd.get(); // now i==42; no warning or error is produced + double d = 42.3; // non-integer double value 42.3 + json jd = d; // stores double value 42.3 + std::int64_t i = jd.template get(); // now i==42; no warning or error is produced ``` Note the last line with throw a [`json.exception.type_error.302`](../../home/exceptions.md#jsonexceptiontype_error302) @@ -259,7 +259,7 @@ The rationale is twofold: if (jd.is_number_integer()) { // if so, do the conversion and use i - std::int64_t i = jd.get(); + std::int64_t i = jd.template get(); // ... } else diff --git a/docs/mkdocs/docs/integration/migration_guide.md b/docs/mkdocs/docs/integration/migration_guide.md index 69dc7eca9..d250f5b20 100644 --- a/docs/mkdocs/docs/integration/migration_guide.md +++ b/docs/mkdocs/docs/integration/migration_guide.md @@ -187,7 +187,7 @@ conversions with calls to [`get`](../api/basic_json/get.md), [`get_to`](../api/b ```cpp nlohmann::json j = "Hello, world!"; - auto s = j.get(); + auto s = j.template get(); ``` === "Future-proof (alternative)" From 5d2754306d67d1e654a1a34e1d2e74439a9d53b3 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Wed, 14 Jun 2023 07:39:09 +0200 Subject: [PATCH 5/5] :money_with_wings: add sponsor --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index ae2a4ad12..43aacf4d5 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,7 @@ You can sponsor this library at [GitHub Sponsors](https://github.com/sponsors/nl - [Steve Sperandeo](https://github.com/homer6) - [Robert Jefe Lindstädt](https://github.com/eljefedelrodeodeljefe) - [Steve Wagner](https://github.com/ciroque) +- [Lion Yang](https://github.com/LionNatsu) Thanks everyone!