| // __ _____ _____ _____ |
| // __| | __| | | | JSON for Modern C++ (supporting code) |
| // | | |__ | | | | | | version 3.12.0 |
| // |_____|_____|_____|_|___| https://github.com/nlohmann/json |
| // |
| // SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me> |
| // SPDX-License-Identifier: MIT |
| |
| #include "doctest_compatibility.h" |
| |
| // This file tests the opt-in JSON_DISABLE_TUPLE_REFERENCE_CONVERSION, so it |
| // defines the macro itself rather than relying on a -D flag, and runs in every |
| // build. |
| #ifdef JSON_DISABLE_TUPLE_REFERENCE_CONVERSION |
| #undef JSON_DISABLE_TUPLE_REFERENCE_CONVERSION |
| #endif |
| |
| #define JSON_DISABLE_TUPLE_REFERENCE_CONVERSION 1 |
| |
| #include <nlohmann/json.hpp> |
| using nlohmann::json; |
| using nlohmann::ordered_json; |
| |
| #include <string> |
| #include <tuple> |
| #include <type_traits> |
| #include <utility> |
| |
| // clang before 4 and GCC before 5 cannot create a std::tuple of basic_json |
| // references at all, with or without JSON_DISABLE_TUPLE_REFERENCE_CONVERSION: |
| // the tuple constructors make them instantiate basic_json's conversion operator |
| // for libstdc++'s internal tuple bases, which fails hard |
| #if (defined(__clang__) && __clang_major__ < 4) || (!defined(__clang__) && defined(__GNUC__) && __GNUC__ < 5) |
| #define SKIP_TESTS_FOR_JSON_REFERENCE_TUPLES |
| #endif |
| |
| TEST_CASE("JSON_DISABLE_TUPLE_REFERENCE_CONVERSION") |
| { |
| SECTION("json is not constructible from a one-element tuple of a json reference") |
| { |
| CHECK_FALSE(std::is_constructible<json, std::tuple<json&>>::value); |
| CHECK_FALSE(std::is_constructible<json, std::tuple<const json&>>::value); |
| CHECK_FALSE(std::is_constructible < json, std::tuple < json && >>::value); |
| CHECK_FALSE(std::is_constructible<json, const std::tuple<json&>&>::value); |
| CHECK_FALSE(std::is_constructible<ordered_json, std::tuple<ordered_json&>>::value); |
| } |
| |
| #ifndef SKIP_TESTS_FOR_JSON_REFERENCE_TUPLES |
| SECTION("issue #2226 - tuple<const json&> from tuple<json&> keeps the reference") |
| { |
| json j = true; |
| const std::tuple<const json&> tup(std::forward_as_tuple(j)); |
| CHECK(&std::get<0>(tup) == &j); |
| } |
| |
| SECTION("tuple<json> from tuple<json&> copies the element") |
| { |
| const json j = {{"key", "value"}}; |
| const std::tuple<json> t1(std::forward_as_tuple(j)); |
| CHECK(std::get<0>(t1) == j); |
| |
| json j2 = "text"; |
| const std::tuple<json> t2(std::forward_as_tuple(std::move(j2))); |
| CHECK(std::get<0>(t2) == "text"); |
| } |
| #endif |
| |
| SECTION("other tuple conversions are not affected") |
| { |
| const json j = true; |
| |
| // one-element tuple holding a json value |
| CHECK(json(std::make_tuple(j)) == json::array({true})); |
| |
| // tuples with more than one element, even when holding references |
| int i = 1; |
| #ifndef SKIP_TESTS_FOR_JSON_REFERENCE_TUPLES |
| CHECK(json(std::forward_as_tuple(i, j)) == json::array({1, true})); |
| CHECK(json(std::forward_as_tuple(j, j)) == json::array({true, true})); |
| #endif |
| |
| // one-element tuples holding references to other types |
| std::string s = "text"; |
| CHECK(json(std::forward_as_tuple(s)) == json::array({"text"})); |
| CHECK(json(std::forward_as_tuple(i)) == json::array({1})); |
| |
| #ifndef SKIP_TESTS_FOR_JSON_REFERENCE_TUPLES |
| // a reference to a different basic_json specialization |
| ordered_json oj = true; |
| CHECK(json(std::forward_as_tuple(oj)) == json::array({true})); |
| #endif |
| } |
| } |