Commitf28fc22introduced const qualifiers on post-(inc-/dec-)rement operators of iterators. These qualifiers prevent the use of basic_json in place of std::ranges::range, which requires the post-increment operator to be equality-preserving. These changes appear to be the result of ICC compiler suggestions, and no further explanation is discernible from the PR discussion (#858). Further testing revealed, that clang-tidy also suggests adding const to prevent "accidental mutation of a temporary object". As an alternative, this commit partially revertsf28fc22, removing all added const qualifiers from return types and adds lvalue reference qualifiers to the operator member functions instead. Unit tests ensure the operators remain equality-preserving and accidental mutation of temporaries following post-(inc-/dec-)rement is prohibited. Fixes #3331.
124 lines
2.8 KiB
C++
124 lines
2.8 KiB
C++
#pragma once
|
|
|
|
#include <cstddef> // ptrdiff_t
|
|
#include <limits> // numeric_limits
|
|
|
|
#include <nlohmann/detail/macro_scope.hpp>
|
|
|
|
namespace nlohmann
|
|
{
|
|
namespace detail
|
|
{
|
|
/*
|
|
@brief an iterator for primitive JSON types
|
|
|
|
This class models an iterator for primitive JSON types (boolean, number,
|
|
string). It's only purpose is to allow the iterator/const_iterator classes
|
|
to "iterate" over primitive values. Internally, the iterator is modeled by
|
|
a `difference_type` variable. Value begin_value (`0`) models the begin,
|
|
end_value (`1`) models past the end.
|
|
*/
|
|
class primitive_iterator_t
|
|
{
|
|
private:
|
|
using difference_type = std::ptrdiff_t;
|
|
static constexpr difference_type begin_value = 0;
|
|
static constexpr difference_type end_value = begin_value + 1;
|
|
|
|
JSON_PRIVATE_UNLESS_TESTED:
|
|
/// iterator as signed integer type
|
|
difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
|
|
|
|
public:
|
|
constexpr difference_type get_value() const noexcept
|
|
{
|
|
return m_it;
|
|
}
|
|
|
|
/// set iterator to a defined beginning
|
|
void set_begin() noexcept
|
|
{
|
|
m_it = begin_value;
|
|
}
|
|
|
|
/// set iterator to a defined past the end
|
|
void set_end() noexcept
|
|
{
|
|
m_it = end_value;
|
|
}
|
|
|
|
/// return whether the iterator can be dereferenced
|
|
constexpr bool is_begin() const noexcept
|
|
{
|
|
return m_it == begin_value;
|
|
}
|
|
|
|
/// return whether the iterator is at end
|
|
constexpr bool is_end() const noexcept
|
|
{
|
|
return m_it == end_value;
|
|
}
|
|
|
|
friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
|
|
{
|
|
return lhs.m_it == rhs.m_it;
|
|
}
|
|
|
|
friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
|
|
{
|
|
return lhs.m_it < rhs.m_it;
|
|
}
|
|
|
|
primitive_iterator_t operator+(difference_type n) noexcept
|
|
{
|
|
auto result = *this;
|
|
result += n;
|
|
return result;
|
|
}
|
|
|
|
friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
|
|
{
|
|
return lhs.m_it - rhs.m_it;
|
|
}
|
|
|
|
primitive_iterator_t& operator++() noexcept
|
|
{
|
|
++m_it;
|
|
return *this;
|
|
}
|
|
|
|
primitive_iterator_t operator++(int)& noexcept // NOLINT(cert-dcl21-cpp)
|
|
{
|
|
auto result = *this;
|
|
++m_it;
|
|
return result;
|
|
}
|
|
|
|
primitive_iterator_t& operator--() noexcept
|
|
{
|
|
--m_it;
|
|
return *this;
|
|
}
|
|
|
|
primitive_iterator_t operator--(int)& noexcept // NOLINT(cert-dcl21-cpp)
|
|
{
|
|
auto result = *this;
|
|
--m_it;
|
|
return result;
|
|
}
|
|
|
|
primitive_iterator_t& operator+=(difference_type n) noexcept
|
|
{
|
|
m_it += n;
|
|
return *this;
|
|
}
|
|
|
|
primitive_iterator_t& operator-=(difference_type n) noexcept
|
|
{
|
|
m_it -= n;
|
|
return *this;
|
|
}
|
|
};
|
|
} // namespace detail
|
|
} // namespace nlohmann
|