From c5d40f05fe1f4485ac9da543a78d71fac17dee75 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Tue, 29 Sep 2026 16:44:24 +0200 Subject: [PATCH] Fix CI: skip std::pair noexcept assumptions on EDG-based compilers ci_icpc and ci_nvhpc failed to compile unit-ordered_map.cpp: the static assertion that std::pair is not nothrow move-constructible fails there. The EDG front end (Intel icpc 2021.10, NVIDIA nvc++ 25.5) considers the defaulted move constructor of std::pair noexcept even if copying Key can throw. With these compilers, std::vector already moves such elements itself when it grows, and ordered_map correctly leaves growing to it. The same misjudgement makes std::vector call std::terminate when a key copy throws during growth, so the exception-safety test with throwing_key would abort on these compilers as well. Skip the static assertion and the exception-safety section when __EDG__ is defined. Verified with icpc 2021.10 (-std=gnu++11) and nvc++ 25.5 (C++11 and C++17) on Compiler Explorer: unit-ordered_map and unit-disabled_exceptions build and pass. Signed-off-by: Niels Lohmann --- tests/src/unit-ordered_map.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/tests/src/unit-ordered_map.cpp b/tests/src/unit-ordered_map.cpp index 538826b5c..98b6fa0d1 100644 --- a/tests/src/unit-ordered_map.cpp +++ b/tests/src/unit-ordered_map.cpp @@ -17,6 +17,14 @@ using nlohmann::ordered_map; #include #include +// The EDG front end (Intel icpc, NVIDIA nvc++) considers the defaulted move +// constructor of std::pair noexcept even if copying Key can +// throw. std::vector then moves such elements itself when it grows (and calls +// std::terminate if a key copy throws), so ordered_map leaves growing to it. +#if defined(__EDG__) + #define JSON_TEST_PAIR_MOVE_IS_NOEXCEPT +#endif + namespace { // number of copies made of counted values @@ -46,7 +54,7 @@ struct counted // NOLINT(cppcoreguidelines-special-member-functions,hicpp-specia } }; -#if !defined(JSON_NOEXCEPTION) +#if !defined(JSON_NOEXCEPTION) && !defined(JSON_TEST_PAIR_MOVE_IS_NOEXCEPT) // number of throwing_key copies that still succeed; the next one throws // (a negative value means that copies never throw) int key_copies_until_throw = -1; @@ -86,7 +94,9 @@ struct no_default // ordered_json must keep moving its values when an object grows using ordered_object_t = nlohmann::ordered_json::object_t; -static_assert(!std::is_nothrow_move_constructible::value, "std::vector would move the elements itself"); +#if !defined(JSON_TEST_PAIR_MOVE_IS_NOEXCEPT) + static_assert(!std::is_nothrow_move_constructible::value, "std::vector would move the elements itself"); +#endif static_assert(std::is_copy_constructible::value, "keys must be copyable"); static_assert(std::is_default_constructible::value, "values must be default-constructible"); static_assert(std::is_nothrow_move_assignable::value, "values must be nothrow move-assignable"); @@ -566,7 +576,7 @@ TEST_CASE("ordered_map growth") } } -#if !defined(JSON_NOEXCEPTION) +#if !defined(JSON_NOEXCEPTION) && !defined(JSON_TEST_PAIR_MOVE_IS_NOEXCEPT) SECTION("the container is unchanged if growing it throws") { ordered_map om;