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.
120 lines
3.4 KiB
C++
120 lines
3.4 KiB
C++
#pragma once
|
|
|
|
#include <cstddef> // ptrdiff_t
|
|
#include <iterator> // reverse_iterator
|
|
#include <utility> // declval
|
|
|
|
namespace nlohmann
|
|
{
|
|
namespace detail
|
|
{
|
|
//////////////////////
|
|
// reverse_iterator //
|
|
//////////////////////
|
|
|
|
/*!
|
|
@brief a template for a reverse iterator class
|
|
|
|
@tparam Base the base iterator type to reverse. Valid types are @ref
|
|
iterator (to create @ref reverse_iterator) and @ref const_iterator (to
|
|
create @ref const_reverse_iterator).
|
|
|
|
@requirement The class satisfies the following concept requirements:
|
|
-
|
|
[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
|
|
The iterator that can be moved can be moved in both directions (i.e.
|
|
incremented and decremented).
|
|
- [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator):
|
|
It is possible to write to the pointed-to element (only if @a Base is
|
|
@ref iterator).
|
|
|
|
@since version 1.0.0
|
|
*/
|
|
template<typename Base>
|
|
class json_reverse_iterator : public std::reverse_iterator<Base>
|
|
{
|
|
public:
|
|
using difference_type = std::ptrdiff_t;
|
|
/// shortcut to the reverse iterator adapter
|
|
using base_iterator = std::reverse_iterator<Base>;
|
|
/// the reference type for the pointed-to element
|
|
using reference = typename Base::reference;
|
|
|
|
/// create reverse iterator from iterator
|
|
explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
|
|
: base_iterator(it) {}
|
|
|
|
/// create reverse iterator from base class
|
|
explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
|
|
|
|
/// post-increment (it++)
|
|
json_reverse_iterator operator++(int)& // NOLINT(cert-dcl21-cpp)
|
|
{
|
|
return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
|
|
}
|
|
|
|
/// pre-increment (++it)
|
|
json_reverse_iterator& operator++()
|
|
{
|
|
return static_cast<json_reverse_iterator&>(base_iterator::operator++());
|
|
}
|
|
|
|
/// post-decrement (it--)
|
|
json_reverse_iterator operator--(int)& // NOLINT(cert-dcl21-cpp)
|
|
{
|
|
return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
|
|
}
|
|
|
|
/// pre-decrement (--it)
|
|
json_reverse_iterator& operator--()
|
|
{
|
|
return static_cast<json_reverse_iterator&>(base_iterator::operator--());
|
|
}
|
|
|
|
/// add to iterator
|
|
json_reverse_iterator& operator+=(difference_type i)
|
|
{
|
|
return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
|
|
}
|
|
|
|
/// add to iterator
|
|
json_reverse_iterator operator+(difference_type i) const
|
|
{
|
|
return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
|
|
}
|
|
|
|
/// subtract from iterator
|
|
json_reverse_iterator operator-(difference_type i) const
|
|
{
|
|
return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
|
|
}
|
|
|
|
/// return difference
|
|
difference_type operator-(const json_reverse_iterator& other) const
|
|
{
|
|
return base_iterator(*this) - base_iterator(other);
|
|
}
|
|
|
|
/// access to successor
|
|
reference operator[](difference_type n) const
|
|
{
|
|
return *(this->operator+(n));
|
|
}
|
|
|
|
/// return the key of an object iterator
|
|
auto key() const -> decltype(std::declval<Base>().key())
|
|
{
|
|
auto it = --this->base();
|
|
return it.key();
|
|
}
|
|
|
|
/// return the value of an iterator
|
|
reference value() const
|
|
{
|
|
auto it = --this->base();
|
|
return it.operator * ();
|
|
}
|
|
};
|
|
} // namespace detail
|
|
} // namespace nlohmann
|