Do not require the container iterators to be nothrow move constructible

iter_impl declared its defaulted move operations noexcept. The exception
specification a defaulted function gets implicitly follows from its members,
here internal_iterator, which holds the object and array iterators. libstdc++
gives std::deque's iterator a user-provided copy constructor without noexcept
before version 11, so the implicit specification is noexcept(false) and does
not match the declared one. That deletes the function -- and with g++ 4.8,
which predates CWG 1778, it is an error outright:

    error: function 'iter_impl<basic_json<std::map, std::deque> >::iter_impl(
    iter_impl&&)' defaulted on its first declaration with an
    exception-specification that differs from the implicit declaration

So std::deque, which this branch documents as a usable array type, could not
be used with an older standard library. Leaving the specification to be
computed cannot mismatch; iteration_proxy_value already spells out the same
condition next door.

The default configuration is unaffected: json::iterator, json::const_iterator
and ordered_json::iterator stay nothrow move constructible and move
assignable, which the test now checks so it cannot regress unnoticed.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
Niels Lohmann
2026-08-28 19:09:51 +00:00
parent 8ce64b9c16
commit 5a2b8a274d
3 changed files with 28 additions and 4 deletions
+14
View File
@@ -14,6 +14,7 @@
#include <map>
#include <memory>
#include <string>
#include <type_traits>
#include <vector>
namespace
@@ -40,6 +41,19 @@ using no_at_json = nlohmann::basic_json<std::map, vector_without_at>;
TEST_CASE("array type without capacity()")
{
SECTION("the iterators of the default configuration stay nothrow movable")
{
// basic_json's iterators take their exception specification from the
// container iterators; std::deque's is not nothrow move constructible
// with older standard libraries, which must not cost the default
// configuration its noexcept
CHECK(std::is_nothrow_move_constructible<nlohmann::json::iterator>::value);
CHECK(std::is_nothrow_move_assignable<nlohmann::json::iterator>::value);
CHECK(std::is_nothrow_move_constructible<nlohmann::json::const_iterator>::value);
CHECK(std::is_move_constructible<deque_json::iterator>::value);
CHECK(std::is_move_assignable<deque_json::iterator>::value);
}
SECTION("adding elements")
{
deque_json j = deque_json::array();