From 8b14c9b305bfc2aac685825db2e543f98526b3a2 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Tue, 21 Jul 2020 23:00:56 +0200 Subject: [PATCH 1/4] :rotating_light: fix warnings --- include/nlohmann/detail/input/binary_reader.hpp | 2 +- include/nlohmann/json.hpp | 2 +- single_include/nlohmann/json.hpp | 4 ++-- test/src/unit-cbor.cpp | 8 ++++---- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/nlohmann/detail/input/binary_reader.hpp b/include/nlohmann/detail/input/binary_reader.hpp index 0b649d02..72e652a4 100644 --- a/include/nlohmann/detail/input/binary_reader.hpp +++ b/include/nlohmann/detail/input/binary_reader.hpp @@ -2279,7 +2279,7 @@ class binary_reader success = false; break; } - result.push_back(std::char_traits::to_char_type(current)); + result.push_back(static_cast(current)); }; return success; } diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index 986cf71f..c7ccb750 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -7507,7 +7507,7 @@ class basic_json const bool allow_exceptions = true, const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) { - return from_cbor(ptr, ptr + len, strict, tag_handler); + return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler); } diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 9476994a..dd09e18b 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -8264,7 +8264,7 @@ class binary_reader success = false; break; } - result.push_back(std::char_traits::to_char_type(current)); + result.push_back(static_cast(current)); }; return success; } @@ -23786,7 +23786,7 @@ class basic_json const bool allow_exceptions = true, const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) { - return from_cbor(ptr, ptr + len, strict, tag_handler); + return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler); } diff --git a/test/src/unit-cbor.cpp b/test/src/unit-cbor.cpp index 2aeac10d..ee32983a 100644 --- a/test/src/unit-cbor.cpp +++ b/test/src/unit-cbor.cpp @@ -2558,10 +2558,10 @@ TEST_CASE("Tagged values") SECTION("0xC6..0xD4") { - for (std::uint8_t b : - { - 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4 - }) + for (auto b : std::vector + { + 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4 + }) { // add tag to value auto v_tagged = v; From 6bd38a2cb9f42b78abfe18db35c5a1fb773d9c2c Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Wed, 22 Jul 2020 09:02:55 +0200 Subject: [PATCH 2/4] :construction_worker: merge Gitlab actions --- .github/workflows/windows.yml | 55 +++++++++++++++++++++++++- .github/workflows/windows_clang.yml | 32 --------------- .github/workflows/windows_clang_cl.yml | 30 -------------- 3 files changed, 53 insertions(+), 64 deletions(-) delete mode 100644 .github/workflows/windows_clang.yml delete mode 100644 .github/workflows/windows_clang_cl.yml diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 476b21df..5846cf75 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -3,8 +3,7 @@ name: Windows on: [push, pull_request] jobs: - build: - + msvc2019: runs-on: windows-latest steps: @@ -15,3 +14,55 @@ jobs: run: cmake --build build --parallel 10 - name: test run: cd build ; ctest -j 10 -C Debug --exclude-regex "test-unicode" --output-on-failure + + clang9: + runs-on: windows-latest + + steps: + - uses: actions/checkout@v1 + - name: install Clang + run: curl -fsSL -o LLVM9.exe https://releases.llvm.org/9.0.0/LLVM-9.0.0-win64.exe ; 7z x LLVM9.exe -y -o"C:/Program Files/LLVM" + - name: cmake + run: cmake -S . -B build -DCMAKE_CXX_COMPILER="C:/Program Files/LLVM/bin/clang++.exe" -G"MinGW Makefiles" -DCMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On + - name: build + run: cmake --build build --parallel 10 + - name: test + run: cd build ; ctest -j 10 -C Debug --exclude-regex "test-unicode" --output-on-failure + + clang10: + runs-on: windows-latest + + steps: + - uses: actions/checkout@v1 + - name: install Clang + run: curl -fsSL -o LLVM10.exe https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/LLVM-10.0.0-win64.exe ; 7z x LLVM10.exe -y -o"C:/Program Files/LLVM" + - name: cmake + run: cmake -S . -B build -DCMAKE_CXX_COMPILER="C:/Program Files/LLVM/bin/clang++.exe" -G"MinGW Makefiles" -DCMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On + - name: build + run: cmake --build build --parallel 10 + - name: test + run: cd build ; ctest -j 10 -C Debug --exclude-regex "test-unicode" --output-on-failure + + clang-cl-10-x64: + runs-on: windows-latest + + steps: + - uses: actions/checkout@v1 + - name: cmake + run: cmake -S . -B build -G "Visual Studio 16 2019" -A x64 -T ClangCL -DJSON_BuildTests=On + - name: build + run: cmake --build build --config Debug --parallel 10 + - name: test + run: cd build ; ctest -j 10 -C Debug --exclude-regex "test-unicode" --output-on-failure + + clang-cl-10-x86: + runs-on: windows-latest + + steps: + - uses: actions/checkout@v1 + - name: cmake + run: cmake -S . -B build -G "Visual Studio 16 2019" -A Win32 -T ClangCL -DJSON_BuildTests=On + - name: build + run: cmake --build build --config Debug --parallel 10 + - name: test + run: cd build ; ctest -j 10 -C Debug --exclude-regex "test-unicode" --output-on-failure diff --git a/.github/workflows/windows_clang.yml b/.github/workflows/windows_clang.yml deleted file mode 100644 index cbf0a8c8..00000000 --- a/.github/workflows/windows_clang.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: Windows - -on: [push, pull_request] - -jobs: - clang9: - runs-on: windows-latest - - steps: - - uses: actions/checkout@v1 - - name: install Clang - run: curl -fsSL -o LLVM9.exe https://releases.llvm.org/9.0.0/LLVM-9.0.0-win64.exe ; 7z x LLVM9.exe -y -o"C:/Program Files/LLVM" - - name: cmake - run: cmake -S . -B build -DCMAKE_CXX_COMPILER="C:/Program Files/LLVM/bin/clang++.exe" -G"MinGW Makefiles" -DCMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On - - name: build - run: cmake --build build --parallel 10 - - name: test - run: cd build ; ctest -j 10 -C Debug --exclude-regex "test-unicode" --output-on-failure - - clang10: - runs-on: windows-latest - - steps: - - uses: actions/checkout@v1 - - name: install Clang - run: curl -fsSL -o LLVM10.exe https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/LLVM-10.0.0-win64.exe ; 7z x LLVM10.exe -y -o"C:/Program Files/LLVM" - - name: cmake - run: cmake -S . -B build -DCMAKE_CXX_COMPILER="C:/Program Files/LLVM/bin/clang++.exe" -G"MinGW Makefiles" -DCMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On - - name: build - run: cmake --build build --parallel 10 - - name: test - run: cd build ; ctest -j 10 -C Debug --exclude-regex "test-unicode" --output-on-failure diff --git a/.github/workflows/windows_clang_cl.yml b/.github/workflows/windows_clang_cl.yml deleted file mode 100644 index 4b5a5f5a..00000000 --- a/.github/workflows/windows_clang_cl.yml +++ /dev/null @@ -1,30 +0,0 @@ -name: Windows - -on: [push, pull_request] - -jobs: - clang-cl-10-x64: - - runs-on: windows-latest - - steps: - - uses: actions/checkout@v1 - - name: cmake - run: cmake -S . -B build -G "Visual Studio 16 2019" -A x64 -T ClangCL -DJSON_BuildTests=On - - name: build - run: cmake --build build --config Debug --parallel 10 - - name: test - run: cd build ; ctest -j 10 -C Debug --exclude-regex "test-unicode" --output-on-failure - - clang-cl-10-x86: - - runs-on: windows-latest - - steps: - - uses: actions/checkout@v1 - - name: cmake - run: cmake -S . -B build -G "Visual Studio 16 2019" -A Win32 -T ClangCL -DJSON_BuildTests=On - - name: build - run: cmake --build build --config Debug --parallel 10 - - name: test - run: cd build ; ctest -j 10 -C Debug --exclude-regex "test-unicode" --output-on-failure From 74b446f5fdec1a829c9cdfdccfbd5ba873562a49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20DELRIEU?= Date: Thu, 16 Jul 2020 11:11:35 +0200 Subject: [PATCH 3/4] add a switch to enable implicit conversions (defaults to true) wrap implicit conversions tests around the JSON_USE_IMPLICIT_CONVERSIONS macro --- CMakeLists.txt | 7 +++ .../nlohmann/detail/conversions/from_json.hpp | 10 ++-- include/nlohmann/detail/macro_scope.hpp | 10 ++++ include/nlohmann/detail/macro_unscope.hpp | 1 + include/nlohmann/detail/meta/type_traits.hpp | 10 ++++ include/nlohmann/json.hpp | 19 +++---- single_include/nlohmann/json.hpp | 50 ++++++++++++++----- test/src/unit-cbor.cpp | 20 ++++---- test/src/unit-constructor1.cpp | 8 +-- test/src/unit-conversions.cpp | 23 +++++++-- test/src/unit-readme.cpp | 10 ++-- test/src/unit-regression.cpp | 38 +++++++++----- test/src/unit-udt.cpp | 2 + test/src/unit-udt_macro.cpp | 5 +- test/src/unit-unicode.cpp | 2 +- 15 files changed, 151 insertions(+), 64 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5df3f99f..1b18b83d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,6 +24,7 @@ endif () option(JSON_BuildTests "Build the unit tests when BUILD_TESTING is enabled." ON) option(JSON_Install "Install CMake targets during install step." ON) option(JSON_MultipleHeaders "Use non-amalgamated version of the library." OFF) +option(JSON_ImplicitConversions "Enable implicit conversions" ON) ## ## CONFIGURATION @@ -60,6 +61,12 @@ else() target_compile_features(${NLOHMANN_JSON_TARGET_NAME} INTERFACE cxx_std_11) endif() +target_compile_definitions( + ${NLOHMANN_JSON_TARGET_NAME} + INTERFACE + JSON_USE_IMPLICIT_CONVERSIONS=$ +) + target_include_directories( ${NLOHMANN_JSON_TARGET_NAME} INTERFACE diff --git a/include/nlohmann/detail/conversions/from_json.hpp b/include/nlohmann/detail/conversions/from_json.hpp index 03e8d367..438b84a2 100644 --- a/include/nlohmann/detail/conversions/from_json.hpp +++ b/include/nlohmann/detail/conversions/from_json.hpp @@ -128,7 +128,7 @@ void from_json(const BasicJsonType& j, EnumType& e) // forward_list doesn't have an insert method template::value, int> = 0> + enable_if_t::value, int> = 0> void from_json(const BasicJsonType& j, std::forward_list& l) { if (JSON_HEDLEY_UNLIKELY(!j.is_array())) @@ -145,7 +145,7 @@ void from_json(const BasicJsonType& j, std::forward_list& l) // valarray doesn't have an insert method template::value, int> = 0> + enable_if_t::value, int> = 0> void from_json(const BasicJsonType& j, std::valarray& l) { if (JSON_HEDLEY_UNLIKELY(!j.is_array())) @@ -153,7 +153,11 @@ void from_json(const BasicJsonType& j, std::valarray& l) JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); } l.resize(j.size()); - std::copy(j.begin(), j.end(), std::begin(l)); + std::transform(j.begin(), j.end(), std::begin(l), + [](const BasicJsonType & elem) + { + return elem.template get(); + }); } template diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index 5d3e00f4..c32a46d1 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -284,3 +284,13 @@ #define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \ void to_json(nlohmann::json& j, const Type& t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ void from_json(const nlohmann::json& j, Type& t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + +#ifndef JSON_USE_IMPLICIT_CONVERSIONS + #define JSON_USE_IMPLICIT_CONVERSIONS 1 +#endif + +#if JSON_USE_IMPLICIT_CONVERSIONS + #define JSON_EXPLICIT +#else + #define JSON_EXPLICIT explicit +#endif diff --git a/include/nlohmann/detail/macro_unscope.hpp b/include/nlohmann/detail/macro_unscope.hpp index 04415061..eb706511 100644 --- a/include/nlohmann/detail/macro_unscope.hpp +++ b/include/nlohmann/detail/macro_unscope.hpp @@ -18,5 +18,6 @@ #undef JSON_HAS_CPP_17 #undef NLOHMANN_BASIC_JSON_TPL_DECLARATION #undef NLOHMANN_BASIC_JSON_TPL +#undef JSON_EXPLICIT #include diff --git a/include/nlohmann/detail/meta/type_traits.hpp b/include/nlohmann/detail/meta/type_traits.hpp index 2da7b363..ac143bec 100644 --- a/include/nlohmann/detail/meta/type_traits.hpp +++ b/include/nlohmann/detail/meta/type_traits.hpp @@ -94,6 +94,16 @@ using get_template_function = decltype(std::declval().template get()); template struct has_from_json : std::false_type {}; +// trait checking if j.get is valid +// use this trait instead of std::is_constructible or std::is_convertible, +// both rely on, or make use of implicit conversions, and thus fail when T +// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958) +template +struct is_getable +{ + static constexpr bool value = is_detected::value; +}; + template struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index 986cf71f..975c5451 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -3229,7 +3229,7 @@ class basic_json #endif && detail::is_detected::value , int >::type = 0 > - operator ValueType() const + JSON_EXPLICIT operator ValueType() const { // delegate the call to get<>() const return get(); @@ -3784,8 +3784,9 @@ class basic_json @since version 1.0.0 */ + // using std::is_convertible in a std::enable_if will fail when using explicit conversions template < class ValueType, typename std::enable_if < - std::is_convertible::value + detail::is_getable::value && !std::is_same::value, int >::type = 0 > ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const { @@ -3796,7 +3797,7 @@ class basic_json const auto it = find(key); if (it != end()) { - return *it; + return it->template get(); } return default_value; @@ -3858,7 +3859,7 @@ class basic_json @since version 2.0.2 */ template::value, int>::type = 0> + detail::is_getable::value, int>::type = 0> ValueType value(const json_pointer& ptr, const ValueType& default_value) const { // at only works for objects @@ -3867,7 +3868,7 @@ class basic_json // if pointer resolves a value, return it or use default value JSON_TRY { - return ptr.get_checked(this); + return ptr.get_checked(this).template get(); } JSON_INTERNAL_CATCH (out_of_range&) { @@ -8341,8 +8342,8 @@ class basic_json } // collect mandatory members - const std::string op = get_value("op", "op", true); - const std::string path = get_value(op, "path", true); + const auto op = get_value("op", "op", true).template get(); + const auto path = get_value(op, "path", true).template get(); json_pointer ptr(path); switch (get_op(op)) @@ -8368,7 +8369,7 @@ class basic_json case patch_operations::move: { - const std::string from_path = get_value("move", "from", true); + const auto from_path = get_value("move", "from", true).template get(); json_pointer from_ptr(from_path); // the "from" location must exist - use at() @@ -8385,7 +8386,7 @@ class basic_json case patch_operations::copy: { - const std::string from_path = get_value("copy", "from", true); + const auto from_path = get_value("copy", "from", true).template get(); const json_pointer from_ptr(from_path); // the "from" location must exist - use at() diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 9476994a..142baffd 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -2302,6 +2302,16 @@ JSON_HEDLEY_DIAGNOSTIC_POP void to_json(nlohmann::json& j, const Type& t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ void from_json(const nlohmann::json& j, Type& t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } +#ifndef JSON_USE_IMPLICIT_CONVERSIONS + #define JSON_USE_IMPLICIT_CONVERSIONS 1 +#endif + +#if JSON_USE_IMPLICIT_CONVERSIONS + #define JSON_EXPLICIT +#else + #define JSON_EXPLICIT explicit +#endif + namespace nlohmann { @@ -3022,6 +3032,16 @@ using get_template_function = decltype(std::declval().template get()); template struct has_from_json : std::false_type {}; +// trait checking if j.get is valid +// use this trait instead of std::is_constructible or std::is_convertible, +// both rely on, or make use of implicit conversions, and thus fail when T +// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958) +template +struct is_getable +{ + static constexpr bool value = is_detected::value; +}; + template struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> @@ -3507,7 +3527,7 @@ void from_json(const BasicJsonType& j, EnumType& e) // forward_list doesn't have an insert method template::value, int> = 0> + enable_if_t::value, int> = 0> void from_json(const BasicJsonType& j, std::forward_list& l) { if (JSON_HEDLEY_UNLIKELY(!j.is_array())) @@ -3524,7 +3544,7 @@ void from_json(const BasicJsonType& j, std::forward_list& l) // valarray doesn't have an insert method template::value, int> = 0> + enable_if_t::value, int> = 0> void from_json(const BasicJsonType& j, std::valarray& l) { if (JSON_HEDLEY_UNLIKELY(!j.is_array())) @@ -3532,7 +3552,11 @@ void from_json(const BasicJsonType& j, std::valarray& l) JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); } l.resize(j.size()); - std::copy(j.begin(), j.end(), std::begin(l)); + std::transform(j.begin(), j.end(), std::begin(l), + [](const BasicJsonType & elem) + { + return elem.template get(); + }); } template @@ -19508,7 +19532,7 @@ class basic_json #endif && detail::is_detected::value , int >::type = 0 > - operator ValueType() const + JSON_EXPLICIT operator ValueType() const { // delegate the call to get<>() const return get(); @@ -20063,8 +20087,9 @@ class basic_json @since version 1.0.0 */ + // using std::is_convertible in a std::enable_if will fail when using explicit conversions template < class ValueType, typename std::enable_if < - std::is_convertible::value + detail::is_getable::value && !std::is_same::value, int >::type = 0 > ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const { @@ -20075,7 +20100,7 @@ class basic_json const auto it = find(key); if (it != end()) { - return *it; + return it->template get(); } return default_value; @@ -20137,7 +20162,7 @@ class basic_json @since version 2.0.2 */ template::value, int>::type = 0> + detail::is_getable::value, int>::type = 0> ValueType value(const json_pointer& ptr, const ValueType& default_value) const { // at only works for objects @@ -20146,7 +20171,7 @@ class basic_json // if pointer resolves a value, return it or use default value JSON_TRY { - return ptr.get_checked(this); + return ptr.get_checked(this).template get(); } JSON_INTERNAL_CATCH (out_of_range&) { @@ -24620,8 +24645,8 @@ class basic_json } // collect mandatory members - const std::string op = get_value("op", "op", true); - const std::string path = get_value(op, "path", true); + const auto op = get_value("op", "op", true).template get(); + const auto path = get_value(op, "path", true).template get(); json_pointer ptr(path); switch (get_op(op)) @@ -24647,7 +24672,7 @@ class basic_json case patch_operations::move: { - const std::string from_path = get_value("move", "from", true); + const auto from_path = get_value("move", "from", true).template get(); json_pointer from_ptr(from_path); // the "from" location must exist - use at() @@ -24664,7 +24689,7 @@ class basic_json case patch_operations::copy: { - const std::string from_path = get_value("copy", "from", true); + const auto from_path = get_value("copy", "from", true).template get(); const json_pointer from_ptr(from_path); // the "from" location must exist - use at() @@ -25086,6 +25111,7 @@ inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std #undef JSON_HAS_CPP_17 #undef NLOHMANN_BASIC_JSON_TPL_DECLARATION #undef NLOHMANN_BASIC_JSON_TPL +#undef JSON_EXPLICIT // #include #undef JSON_HEDLEY_ALWAYS_INLINE diff --git a/test/src/unit-cbor.cpp b/test/src/unit-cbor.cpp index 2aeac10d..483957d3 100644 --- a/test/src/unit-cbor.cpp +++ b/test/src/unit-cbor.cpp @@ -1011,21 +1011,21 @@ TEST_CASE("CBOR") SECTION("0 (0 00000 0000000000)") { json j = json::from_cbor(std::vector({0xf9, 0x00, 0x00})); - json::number_float_t d = j; + json::number_float_t d{j}; CHECK(d == 0.0); } SECTION("-0 (1 00000 0000000000)") { json j = json::from_cbor(std::vector({0xf9, 0x80, 0x00})); - json::number_float_t d = j; + json::number_float_t d{j}; CHECK(d == -0.0); } SECTION("2**-24 (0 00000 0000000001)") { json j = json::from_cbor(std::vector({0xf9, 0x00, 0x01})); - json::number_float_t d = j; + json::number_float_t d{j}; CHECK(d == std::pow(2.0, -24.0)); } } @@ -1035,7 +1035,7 @@ TEST_CASE("CBOR") SECTION("infinity (0 11111 0000000000)") { json j = json::from_cbor(std::vector({0xf9, 0x7c, 0x00})); - json::number_float_t d = j; + json::number_float_t d{j}; CHECK(d == std::numeric_limits::infinity()); CHECK(j.dump() == "null"); } @@ -1043,7 +1043,7 @@ TEST_CASE("CBOR") SECTION("-infinity (1 11111 0000000000)") { json j = json::from_cbor(std::vector({0xf9, 0xfc, 0x00})); - json::number_float_t d = j; + json::number_float_t d{j}; CHECK(d == -std::numeric_limits::infinity()); CHECK(j.dump() == "null"); } @@ -1054,21 +1054,21 @@ TEST_CASE("CBOR") SECTION("1 (0 01111 0000000000)") { json j = json::from_cbor(std::vector({0xf9, 0x3c, 0x00})); - json::number_float_t d = j; + json::number_float_t d{j}; CHECK(d == 1); } SECTION("-2 (1 10000 0000000000)") { json j = json::from_cbor(std::vector({0xf9, 0xc0, 0x00})); - json::number_float_t d = j; + json::number_float_t d{j}; CHECK(d == -2); } SECTION("65504 (0 11110 1111111111)") { json j = json::from_cbor(std::vector({0xf9, 0x7b, 0xff})); - json::number_float_t d = j; + json::number_float_t d{j}; CHECK(d == 65504); } } @@ -1076,7 +1076,7 @@ TEST_CASE("CBOR") SECTION("infinity") { json j = json::from_cbor(std::vector({0xf9, 0x7c, 0x00})); - json::number_float_t d = j; + json::number_float_t d{j}; CHECK(!std::isfinite(d)); CHECK(j.dump() == "null"); } @@ -1084,7 +1084,7 @@ TEST_CASE("CBOR") SECTION("NaN") { json j = json::from_cbor(std::vector({0xf9, 0x7e, 0x00})); - json::number_float_t d = j; + json::number_float_t d{j}; CHECK(std::isnan(d)); CHECK(j.dump() == "null"); } diff --git a/test/src/unit-constructor1.cpp b/test/src/unit-constructor1.cpp index e4192d33..8e63d0ce 100644 --- a/test/src/unit-constructor1.cpp +++ b/test/src/unit-constructor1.cpp @@ -341,7 +341,7 @@ TEST_CASE("constructors") CHECK(j.type() == json::value_t::array); CHECK(j == json({1, 2, 3, 4, 5})); - std::valarray jva = j; + auto jva = j.get>(); CHECK(jva.size() == va.size()); for (size_t i = 0; i < jva.size(); ++i) { @@ -356,7 +356,7 @@ TEST_CASE("constructors") CHECK(j.type() == json::value_t::array); CHECK(j == json({1.2, 2.3, 3.4, 4.5, 5.6})); - std::valarray jva = j; + auto jva = j.get>(); CHECK(jva.size() == va.size()); for (size_t i = 0; i < jva.size(); ++i) { @@ -846,7 +846,7 @@ TEST_CASE("constructors") CHECK(j.type() == json::value_t::number_float); // check round trip of NaN - json::number_float_t d = j; + json::number_float_t d{j}; CHECK((std::isnan(d) && std::isnan(n)) == true); // check that NaN is serialized to null @@ -861,7 +861,7 @@ TEST_CASE("constructors") CHECK(j.type() == json::value_t::number_float); // check round trip of infinity - json::number_float_t d = j; + json::number_float_t d{j}; CHECK(d == n); // check that inf is serialized to null diff --git a/test/src/unit-conversions.cpp b/test/src/unit-conversions.cpp index 47ede67c..97a4e6b6 100644 --- a/test/src/unit-conversions.cpp +++ b/test/src/unit-conversions.cpp @@ -189,6 +189,7 @@ TEST_CASE("value conversion") } } +#if JSON_USE_IMPLICIT_CONVERSIONS SECTION("get an object (implicit)") { json::object_t o_reference = {{"object", json::object()}, @@ -230,6 +231,7 @@ TEST_CASE("value conversion") CHECK(json(o) == j); } } +#endif SECTION("get an array (explicit)") { @@ -276,7 +278,8 @@ TEST_CASE("value conversion") SECTION("reserve is called on containers that supports it") { // make sure all values are properly copied - std::vector v2 = json({1, 2, 3, 4, 5, 6, 7, 8, 9, 10}); + json j({1, 2, 3, 4, 5, 6, 7, 8, 9, 10}); + auto v2 = j.get>(); CHECK(v2.size() == 10); } #endif @@ -405,6 +408,7 @@ TEST_CASE("value conversion") } } +#if JSON_USE_IMPLICIT_CONVERSIONS SECTION("get an array (implicit)") { json::array_t a_reference{json(1), json(1u), json(2.2), @@ -441,6 +445,7 @@ TEST_CASE("value conversion") CHECK(json(a) == j); } } +#endif SECTION("get a string (explicit)") { @@ -598,6 +603,7 @@ TEST_CASE("value conversion") } +#if JSON_USE_IMPLICIT_CONVERSIONS SECTION("get a string (implicit)") { json::string_t s_reference{"Hello world"}; @@ -623,6 +629,7 @@ TEST_CASE("value conversion") CHECK(json(s) == j); } } +#endif SECTION("get a boolean (explicit)") { @@ -695,6 +702,7 @@ TEST_CASE("value conversion") } } +#if JSON_USE_IMPLICIT_CONVERSIONS SECTION("get a boolean (implicit)") { json::boolean_t b_reference{true}; @@ -712,6 +720,7 @@ TEST_CASE("value conversion") CHECK(json(b) == j); } } +#endif SECTION("get an integer number (explicit)") { @@ -962,6 +971,7 @@ TEST_CASE("value conversion") } } +#if JSON_USE_IMPLICIT_CONVERSIONS SECTION("get an integer number (implicit)") { json::number_integer_t n_reference{42}; @@ -1173,6 +1183,7 @@ TEST_CASE("value conversion") CHECK(json(n) == j_unsigned); } } +#endif SECTION("get a floating-point number (explicit)") { @@ -1234,6 +1245,7 @@ TEST_CASE("value conversion") } } +#if JSON_USE_IMPLICIT_CONVERSIONS SECTION("get a floating-point number (implicit)") { json::number_float_t n_reference{42.23}; @@ -1257,6 +1269,7 @@ TEST_CASE("value conversion") CHECK(json(n).m_value.number_float == Approx(j.m_value.number_float)); } } +#endif SECTION("get a binary value (explicit)") { @@ -1364,6 +1377,7 @@ TEST_CASE("value conversion") } } +#if JSON_USE_IMPLICIT_CONVERSIONS SECTION("get a binary value (implicit)") { json::binary_t n_reference{{1, 2, 3}}; @@ -1375,6 +1389,7 @@ TEST_CASE("value conversion") CHECK(*json(b).m_value.binary == *j.m_value.binary); } } +#endif SECTION("get an enum") { @@ -1481,15 +1496,15 @@ TEST_CASE("value conversion") SECTION("std::array is larger than JSON") { std::array arr6 = {{1, 2, 3, 4, 5, 6}}; - CHECK_THROWS_AS(arr6 = j1, json::out_of_range&); - CHECK_THROWS_WITH(arr6 = j1, "[json.exception.out_of_range.401] " + CHECK_THROWS_AS(j1.get_to(arr6), json::out_of_range&); + CHECK_THROWS_WITH(j1.get_to(arr6), "[json.exception.out_of_range.401] " "array index 4 is out of range"); } SECTION("std::array is smaller than JSON") { std::array arr2 = {{8, 9}}; - arr2 = j1; + j1.get_to(arr2); CHECK(arr2[0] == 1); CHECK(arr2[1] == 2); } diff --git a/test/src/unit-readme.cpp b/test/src/unit-readme.cpp index e6089a32..e9193cf0 100644 --- a/test/src/unit-readme.cpp +++ b/test/src/unit-readme.cpp @@ -174,9 +174,9 @@ TEST_CASE("README" * doctest::skip()) } // getter/setter - const std::string tmp = j[0]; + const auto tmp = j[0].get(); j[1] = 42; - bool foo = j.at(2); + bool foo{j.at(2)}; CHECK(foo == true); // other stuff @@ -258,18 +258,18 @@ TEST_CASE("README" * doctest::skip()) // strings std::string s1 = "Hello, world!"; json js = s1; - std::string s2 = js; + auto s2 = js.get(); // Booleans bool b1 = true; json jb = b1; - bool b2 = jb; + bool b2{jb}; CHECK(b2 == true); // numbers int i = 42; json jn = i; - double f = jn; + double f{jn}; CHECK(f == 42); // etc. diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp index b33c39ec..649ac656 100644 --- a/test/src/unit-regression.cpp +++ b/test/src/unit-regression.cpp @@ -240,12 +240,12 @@ TEST_CASE("regression tests") { json j1 = NAN; CHECK(j1.is_number_float()); - json::number_float_t f1 = j1; + json::number_float_t f1{j1}; CHECK(std::isnan(f1)); json j2 = json::number_float_t(NAN); CHECK(j2.is_number_float()); - json::number_float_t f2 = j2; + json::number_float_t f2{j2}; CHECK(std::isnan(f2)); } @@ -253,12 +253,12 @@ TEST_CASE("regression tests") { json j1 = INFINITY; CHECK(j1.is_number_float()); - json::number_float_t f1 = j1; + json::number_float_t f1{j1}; CHECK(!std::isfinite(f1)); json j2 = json::number_float_t(INFINITY); CHECK(j2.is_number_float()); - json::number_float_t f2 = j2; + json::number_float_t f2{j2}; CHECK(!std::isfinite(f2)); } } @@ -332,11 +332,11 @@ TEST_CASE("regression tests") json j; ss >> j; - std::string test = j["Test"]; + auto test = j["Test"].get(); CHECK(test == "Test1"); - int number = j["Number"]; + int number{j["Number"]}; CHECK(number == 100); - float foo = j["Foo"]; + float foo{j["Foo"]}; CHECK(static_cast(foo) == Approx(42.42)); } @@ -453,6 +453,7 @@ TEST_CASE("regression tests") CHECK(j["string"] == "\u0007\u0007"); } +#if JSON_USE_IMPLICIT_CONVERSIONS SECTION("issue #144 - implicit assignment to std::string fails") { json o = {{"name", "value"}}; @@ -470,6 +471,7 @@ TEST_CASE("regression tests") CHECK_THROWS_AS(s2 = o["int"], json::type_error); CHECK_THROWS_WITH(s2 = o["int"], "[json.exception.type_error.302] type must be string, but is number"); } +#endif SECTION("issue #146 - character following a surrogate pair is skipped") { @@ -689,7 +691,7 @@ TEST_CASE("regression tests") {"object", {{"key1", 1}, {"key2", 2}}}, }; - int at_integer = j.at("/object/key2"_json_pointer); + int at_integer{j.at("/object/key2"_json_pointer)}; int val_integer = j.value("/object/key2"_json_pointer, 0); CHECK(at_integer == val_integer); @@ -1233,6 +1235,7 @@ TEST_CASE("regression tests") CHECK(j["double_value"].is_number_float()); } +#if JSON_USE_IMPLICIT_CONVERSIONS SECTION("issue #464 - VS2017 implicit to std::string conversion fix") { json v = "test"; @@ -1240,6 +1243,7 @@ TEST_CASE("regression tests") test = v; CHECK(v == "test"); } +#endif SECTION("issue #465 - roundtrip error while parsing 1000000000000000010E5") { @@ -1250,6 +1254,7 @@ TEST_CASE("regression tests") CHECK(s1 == s2); } +#if JSON_USE_IMPLICIT_CONVERSIONS SECTION("issue #473 - inconsistent behavior in conversion to array type") { json j_array = {1, 2, 3, 4}; @@ -1298,6 +1303,7 @@ TEST_CASE("regression tests") CHECK_THROWS_WITH(create(j_null), "[json.exception.type_error.302] type must be array, but is null"); } } +#endif SECTION("issue #486 - json::value_t can't be a map's key type in VC++ 2015") { @@ -1377,6 +1383,7 @@ TEST_CASE("regression tests") CHECK_THROWS_AS(_ = json::parse(vec), json::parse_error&); } +#if JSON_USE_IMPLICIT_CONVERSIONS SECTION("issue #600 - how does one convert a map in Json back to std::map?") { SECTION("example 1") @@ -1409,6 +1416,7 @@ TEST_CASE("regression tests") CHECK(m1 == m2); } } +#endif SECTION("issue #602 - BOM not skipped when using json:parse(iterator)") { @@ -1417,6 +1425,7 @@ TEST_CASE("regression tests") CHECK_NOTHROW(_ = json::parse(i.begin(), i.end())); } +#if JSON_USE_IMPLICIT_CONVERSIONS SECTION("issue #702 - conversion from valarray to json fails to build") { SECTION("original example") @@ -1445,6 +1454,7 @@ TEST_CASE("regression tests") "[json.exception.type_error.302] type must be array, but is null"); } } +#endif SECTION("issue #367 - Behavior of operator>> should more closely resemble that of built-in overloads.") { @@ -1456,9 +1466,9 @@ TEST_CASE("regression tests") i1_2_3 >> j2; i1_2_3 >> j3; - std::map m1 = j1; - std::map m2 = j2; - int i3 = j3; + auto m1 = j1.get>(); + auto m2 = j2.get>(); + int i3{j3}; CHECK( m1 == ( std::map {{ "first", "one" }} )); CHECK( m2 == ( std::map {{ "second", "two" }} )); @@ -1513,6 +1523,7 @@ TEST_CASE("regression tests") CHECK_THROWS_WITH(j.dump(), "[json.exception.type_error.316] invalid UTF-8 byte at index 10: 0x7E"); } +#if JSON_USE_IMPLICIT_CONVERSIONS SECTION("issue #843 - converting to array not working") { json j; @@ -1520,6 +1531,7 @@ TEST_CASE("regression tests") j = ar; ar = j; } +#endif SECTION("issue #894 - invalid RFC6902 copy operation succeeds") { @@ -1632,7 +1644,7 @@ TEST_CASE("regression tests") SECTION("issue #977 - Assigning between different json types") { foo_json lj = ns::foo{3}; - ns::foo ff = lj; + ns::foo ff(lj); CHECK(lj.is_object()); CHECK(lj.size() == 1); CHECK(lj["x"] == 3); @@ -1880,7 +1892,7 @@ TEST_CASE("regression tests") { { json j; - NonDefaultFromJsonStruct x = j; + NonDefaultFromJsonStruct x(j); NonDefaultFromJsonStruct y; CHECK(x == y); } diff --git a/test/src/unit-udt.cpp b/test/src/unit-udt.cpp index 83b61b7c..f391fbdb 100644 --- a/test/src/unit-udt.cpp +++ b/test/src/unit-udt.cpp @@ -312,6 +312,7 @@ TEST_CASE("basic usage" * doctest::test_suite("udt")) CHECK(name.m_val == "new name"); } +#if JSON_USE_IMPLICIT_CONVERSIONS SECTION("implicit conversions") { const udt::contact_book parsed_book = big_json; @@ -335,6 +336,7 @@ TEST_CASE("basic usage" * doctest::test_suite("udt")) CHECK(book_name == udt::name{"C++"}); CHECK(book == parsed_book); } +#endif } } diff --git a/test/src/unit-udt_macro.cpp b/test/src/unit-udt_macro.cpp index ce39ec9b..ce9810a0 100644 --- a/test/src/unit-udt_macro.cpp +++ b/test/src/unit-udt_macro.cpp @@ -243,7 +243,7 @@ TEST_CASE_TEMPLATE("Serialization/deserialization via NLOHMANN_DEFINE_TYPE_INTRU CHECK(json(p1).dump() == "{\"age\":1,\"metadata\":{\"haircuts\":2},\"name\":\"Erik\"}"); // deserialization - T p2 = json(p1); + auto p2 = json(p1).get(); CHECK(p2 == p1); // roundtrip @@ -253,8 +253,7 @@ TEST_CASE_TEMPLATE("Serialization/deserialization via NLOHMANN_DEFINE_TYPE_INTRU // check exception in case of missing field json j = json(p1); j.erase("age"); - T p3; - CHECK_THROWS_WITH_AS(p3 = json(j), "[json.exception.out_of_range.403] key 'age' not found", json::out_of_range); + CHECK_THROWS_WITH_AS(j.get(), "[json.exception.out_of_range.403] key 'age' not found", json::out_of_range); } } diff --git a/test/src/unit-unicode.cpp b/test/src/unit-unicode.cpp index 4f155dcd..fa219f5b 100644 --- a/test/src/unit-unicode.cpp +++ b/test/src/unit-unicode.cpp @@ -1168,7 +1168,7 @@ TEST_CASE("Unicode" * doctest::skip()) continue; } - std::string ptr = s; + auto ptr = s.get(); // tilde must be followed by 0 or 1 if (ptr == "~") From 797329315a07ff8690ba5234ead43ac2f1da1f54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20DELRIEU?= Date: Thu, 16 Jul 2020 11:22:57 +0200 Subject: [PATCH 4/4] add a CI job for explicit conversions on every os --- .travis.yml | 19 ++++++++++++++++++- appveyor.yml | 23 ++++++++++++++++++++++- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index ef6c24b5..bf749c1e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -145,6 +145,11 @@ matrix: - os: osx osx_image: xcode12 + - os: osx + osx_image: xcode12 + env: + - IMPLICIT_CONVERSIONS=OFF + # Linux / GCC - os: linux @@ -203,6 +208,16 @@ matrix: sources: ['ubuntu-toolchain-r-test'] packages: ['g++-9', 'ninja-build'] + - os: linux + compiler: gcc + env: + - COMPILER=g++-9 + - IMPLICIT_CONVERSIONS=OFF + addons: + apt: + sources: ['ubuntu-toolchain-r-test'] + packages: ['g++-9', 'ninja-build'] + - os: linux compiler: gcc env: @@ -315,10 +330,12 @@ script: - if [[ "${COMPILER}" != "" ]]; then export CXX=${COMPILER}; fi # by default, use the single-header version - if [[ "${MULTIPLE_HEADERS}" == "" ]]; then export MULTIPLE_HEADERS=OFF; fi + # by default, use implicit conversions + - if [[ "${IMPLICIT_CONVERSIONS}" == "" ]]; then export IMPLICIT_CONVERSIONS=ON; fi # compile and execute unit tests - mkdir -p build && cd build - - cmake .. ${CMAKE_OPTIONS} -DJSON_MultipleHeaders=${MULTIPLE_HEADERS} -DJSON_BuildTests=On -GNinja && cmake --build . --config Release + - cmake .. ${CMAKE_OPTIONS} -DJSON_MultipleHeaders=${MULTIPLE_HEADERS} -DJSON_ImplicitConversions=${IMPLICIT_CONVERSIONS} -DJSON_BuildTests=On -GNinja && cmake --build . --config Release - ctest -C Release --timeout 2700 -V -j - cd .. diff --git a/appveyor.yml b/appveyor.yml index 73788956..5836f88d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -7,6 +7,7 @@ environment: platform: x86 CXX_FLAGS: "" LINKER_FLAGS: "" + CMAKE_OPTIONS: "" GENERATOR: Visual Studio 14 2015 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 @@ -14,6 +15,7 @@ environment: platform: x86 CXX_FLAGS: "" LINKER_FLAGS: "" + CMAKE_OPTIONS: "" GENERATOR: Visual Studio 15 2017 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 @@ -21,6 +23,7 @@ environment: platform: x86 CXX_FLAGS: "" LINKER_FLAGS: "" + CMAKE_OPTIONS: "" GENERATOR: Visual Studio 16 2019 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 @@ -28,6 +31,7 @@ environment: platform: x64 CXX_FLAGS: "" LINKER_FLAGS: "" + CMAKE_OPTIONS: "" GENERATOR: Visual Studio 16 2019 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 @@ -36,6 +40,7 @@ environment: platform: x86 CXX_FLAGS: "" LINKER_FLAGS: "" + CMAKE_OPTIONS: "" GENERATOR: Ninja - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 @@ -44,6 +49,7 @@ environment: platform: x86 CXX_FLAGS: "" LINKER_FLAGS: "" + CMAKE_OPTIONS: "" GENERATOR: Ninja - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 @@ -51,6 +57,7 @@ environment: platform: x86 CXX_FLAGS: "" LINKER_FLAGS: "" + CMAKE_OPTIONS: "" GENERATOR: Visual Studio 14 2015 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 @@ -59,6 +66,7 @@ environment: name: with_win_header CXX_FLAGS: "" LINKER_FLAGS: "" + CMAKE_OPTIONS: "" GENERATOR: Visual Studio 14 2015 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 @@ -66,6 +74,7 @@ environment: platform: x86 CXX_FLAGS: "/permissive- /std:c++latest /utf-8" LINKER_FLAGS: "" + CMAKE_OPTIONS: "" GENERATOR: Visual Studio 15 2017 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 @@ -73,6 +82,15 @@ environment: platform: x86 CXX_FLAGS: "" LINKER_FLAGS: "" + CMAKE_OPTIONS: "-DJSON_ImplicitConversions=OFF" + GENERATOR: Visual Studio 16 2019 + + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 + configuration: Release + platform: x64 + CXX_FLAGS: "" + LINKER_FLAGS: "" + CMAKE_OPTIONS: "" GENERATOR: Visual Studio 16 2019 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 @@ -80,6 +98,7 @@ environment: platform: x64 CXX_FLAGS: "" LINKER_FLAGS: "" + CMAKE_OPTIONS: "" GENERATOR: Visual Studio 14 2015 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 @@ -87,6 +106,7 @@ environment: platform: x64 CXX_FLAGS: "/permissive- /std:c++latest /Zc:__cplusplus /utf-8 /F4000000" LINKER_FLAGS: "/STACK:4000000" + CMAKE_OPTIONS: "" GENERATOR: Visual Studio 15 2017 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 @@ -94,6 +114,7 @@ environment: platform: x64 CXX_FLAGS: "" LINKER_FLAGS: "" + CMAKE_OPTIONS: "" GENERATOR: Visual Studio 16 2019 init: @@ -112,7 +133,7 @@ before_build: # for with_win_header build, inject the inclusion of Windows.h to the single-header library - ps: if ($env:name -Eq "with_win_header") { $header_path = "single_include\nlohmann\json.hpp" } - ps: if ($env:name -Eq "with_win_header") { "#include `n" + (Get-Content $header_path | Out-String) | Set-Content $header_path } - - if "%GENERATOR%"=="Ninja" (cmake . -G "%GENERATOR%" -DCMAKE_BUILD_TYPE="%configuration%" -DCMAKE_CXX_FLAGS="%CXX_FLAGS%" -DCMAKE_EXE_LINKER_FLAGS="%LINKER_FLAGS%" -DCMAKE_IGNORE_PATH="C:/Program Files/Git/usr/bin" -DJSON_BuildTests=On) else (cmake . -G "%GENERATOR%" -A "%GENERATOR_PLATFORM%" -DCMAKE_CXX_FLAGS="%CXX_FLAGS%" -DCMAKE_EXE_LINKER_FLAGS="%LINKER_FLAGS%" -DCMAKE_IGNORE_PATH="C:/Program Files/Git/usr/bin" -DJSON_BuildTests=On) + - if "%GENERATOR%"=="Ninja" (cmake . -G "%GENERATOR%" -DCMAKE_BUILD_TYPE="%configuration%" -DCMAKE_CXX_FLAGS="%CXX_FLAGS%" -DCMAKE_EXE_LINKER_FLAGS="%LINKER_FLAGS%" -DCMAKE_IGNORE_PATH="C:/Program Files/Git/usr/bin" -DJSON_BuildTests=On "%CMAKE_OPTIONS%") else (cmake . -G "%GENERATOR%" -A "%GENERATOR_PLATFORM%" -DCMAKE_CXX_FLAGS="%CXX_FLAGS%" -DCMAKE_EXE_LINKER_FLAGS="%LINKER_FLAGS%" -DCMAKE_IGNORE_PATH="C:/Program Files/Git/usr/bin" -DJSON_BuildTests=On "%CMAKE_OPTIONS%") build_script: - cmake --build . --config "%configuration%"