Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/nlohmann/detail/iterators/iter_impl.hpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 //     __ _____ _____ _____
0002 //  __|  |   __|     |   | |  JSON for Modern C++
0003 // |  |  |__   |  |  | | | |  version 3.11.3
0004 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
0005 //
0006 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
0007 // SPDX-License-Identifier: MIT
0008 
0009 #pragma once
0010 
0011 #include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
0012 #include <type_traits> // conditional, is_const, remove_const
0013 
0014 #include <nlohmann/detail/exceptions.hpp>
0015 #include <nlohmann/detail/iterators/internal_iterator.hpp>
0016 #include <nlohmann/detail/iterators/primitive_iterator.hpp>
0017 #include <nlohmann/detail/macro_scope.hpp>
0018 #include <nlohmann/detail/meta/cpp_future.hpp>
0019 #include <nlohmann/detail/meta/type_traits.hpp>
0020 #include <nlohmann/detail/value_t.hpp>
0021 
0022 NLOHMANN_JSON_NAMESPACE_BEGIN
0023 namespace detail
0024 {
0025 
0026 // forward declare, to be able to friend it later on
0027 template<typename IteratorType> class iteration_proxy;
0028 template<typename IteratorType> class iteration_proxy_value;
0029 
0030 /*!
0031 @brief a template for a bidirectional iterator for the @ref basic_json class
0032 This class implements a both iterators (iterator and const_iterator) for the
0033 @ref basic_json class.
0034 @note An iterator is called *initialized* when a pointer to a JSON value has
0035       been set (e.g., by a constructor or a copy assignment). If the iterator is
0036       default-constructed, it is *uninitialized* and most methods are undefined.
0037       **The library uses assertions to detect calls on uninitialized iterators.**
0038 @requirement The class satisfies the following concept requirements:
0039 -
0040 [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
0041   The iterator that can be moved can be moved in both directions (i.e.
0042   incremented and decremented).
0043 @since version 1.0.0, simplified in version 2.0.9, change to bidirectional
0044        iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593)
0045 */
0046 template<typename BasicJsonType>
0047 class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
0048 {
0049     /// the iterator with BasicJsonType of different const-ness
0050     using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
0051     /// allow basic_json to access private members
0052     friend other_iter_impl;
0053     friend BasicJsonType;
0054     friend iteration_proxy<iter_impl>;
0055     friend iteration_proxy_value<iter_impl>;
0056 
0057     using object_t = typename BasicJsonType::object_t;
0058     using array_t = typename BasicJsonType::array_t;
0059     // make sure BasicJsonType is basic_json or const basic_json
0060     static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value,
0061                   "iter_impl only accepts (const) basic_json");
0062     // superficial check for the LegacyBidirectionalIterator named requirement
0063     static_assert(std::is_base_of<std::bidirectional_iterator_tag, std::bidirectional_iterator_tag>::value
0064                   &&  std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value,
0065                   "basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement.");
0066 
0067   public:
0068     /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17.
0069     /// The C++ Standard has never required user-defined iterators to derive from std::iterator.
0070     /// A user-defined iterator should provide publicly accessible typedefs named
0071     /// iterator_category, value_type, difference_type, pointer, and reference.
0072     /// Note that value_type is required to be non-const, even for constant iterators.
0073     using iterator_category = std::bidirectional_iterator_tag;
0074 
0075     /// the type of the values when the iterator is dereferenced
0076     using value_type = typename BasicJsonType::value_type;
0077     /// a type to represent differences between iterators
0078     using difference_type = typename BasicJsonType::difference_type;
0079     /// defines a pointer to the type iterated over (value_type)
0080     using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
0081           typename BasicJsonType::const_pointer,
0082           typename BasicJsonType::pointer>::type;
0083     /// defines a reference to the type iterated over (value_type)
0084     using reference =
0085         typename std::conditional<std::is_const<BasicJsonType>::value,
0086         typename BasicJsonType::const_reference,
0087         typename BasicJsonType::reference>::type;
0088 
0089     iter_impl() = default;
0090     ~iter_impl() = default;
0091     iter_impl(iter_impl&&) noexcept = default;
0092     iter_impl& operator=(iter_impl&&) noexcept = default;
0093 
0094     /*!
0095     @brief constructor for a given JSON instance
0096     @param[in] object  pointer to a JSON object for this iterator
0097     @pre object != nullptr
0098     @post The iterator is initialized; i.e. `m_object != nullptr`.
0099     */
0100     explicit iter_impl(pointer object) noexcept : m_object(object)
0101     {
0102         JSON_ASSERT(m_object != nullptr);
0103 
0104         switch (m_object->m_data.m_type)
0105         {
0106             case value_t::object:
0107             {
0108                 m_it.object_iterator = typename object_t::iterator();
0109                 break;
0110             }
0111 
0112             case value_t::array:
0113             {
0114                 m_it.array_iterator = typename array_t::iterator();
0115                 break;
0116             }
0117 
0118             case value_t::null:
0119             case value_t::string:
0120             case value_t::boolean:
0121             case value_t::number_integer:
0122             case value_t::number_unsigned:
0123             case value_t::number_float:
0124             case value_t::binary:
0125             case value_t::discarded:
0126             default:
0127             {
0128                 m_it.primitive_iterator = primitive_iterator_t();
0129                 break;
0130             }
0131         }
0132     }
0133 
0134     /*!
0135     @note The conventional copy constructor and copy assignment are implicitly
0136           defined. Combined with the following converting constructor and
0137           assignment, they support: (1) copy from iterator to iterator, (2)
0138           copy from const iterator to const iterator, and (3) conversion from
0139           iterator to const iterator. However conversion from const iterator
0140           to iterator is not defined.
0141     */
0142 
0143     /*!
0144     @brief const copy constructor
0145     @param[in] other const iterator to copy from
0146     @note This copy constructor had to be defined explicitly to circumvent a bug
0147           occurring on msvc v19.0 compiler (VS 2015) debug build. For more
0148           information refer to: https://github.com/nlohmann/json/issues/1608
0149     */
0150     iter_impl(const iter_impl<const BasicJsonType>& other) noexcept
0151         : m_object(other.m_object), m_it(other.m_it)
0152     {}
0153 
0154     /*!
0155     @brief converting assignment
0156     @param[in] other const iterator to copy from
0157     @return const/non-const iterator
0158     @note It is not checked whether @a other is initialized.
0159     */
0160     iter_impl& operator=(const iter_impl<const BasicJsonType>& other) noexcept
0161     {
0162         if (&other != this)
0163         {
0164             m_object = other.m_object;
0165             m_it = other.m_it;
0166         }
0167         return *this;
0168     }
0169 
0170     /*!
0171     @brief converting constructor
0172     @param[in] other  non-const iterator to copy from
0173     @note It is not checked whether @a other is initialized.
0174     */
0175     iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
0176         : m_object(other.m_object), m_it(other.m_it)
0177     {}
0178 
0179     /*!
0180     @brief converting assignment
0181     @param[in] other  non-const iterator to copy from
0182     @return const/non-const iterator
0183     @note It is not checked whether @a other is initialized.
0184     */
0185     iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp)
0186     {
0187         m_object = other.m_object;
0188         m_it = other.m_it;
0189         return *this;
0190     }
0191 
0192   JSON_PRIVATE_UNLESS_TESTED:
0193     /*!
0194     @brief set the iterator to the first value
0195     @pre The iterator is initialized; i.e. `m_object != nullptr`.
0196     */
0197     void set_begin() noexcept
0198     {
0199         JSON_ASSERT(m_object != nullptr);
0200 
0201         switch (m_object->m_data.m_type)
0202         {
0203             case value_t::object:
0204             {
0205                 m_it.object_iterator = m_object->m_data.m_value.object->begin();
0206                 break;
0207             }
0208 
0209             case value_t::array:
0210             {
0211                 m_it.array_iterator = m_object->m_data.m_value.array->begin();
0212                 break;
0213             }
0214 
0215             case value_t::null:
0216             {
0217                 // set to end so begin()==end() is true: null is empty
0218                 m_it.primitive_iterator.set_end();
0219                 break;
0220             }
0221 
0222             case value_t::string:
0223             case value_t::boolean:
0224             case value_t::number_integer:
0225             case value_t::number_unsigned:
0226             case value_t::number_float:
0227             case value_t::binary:
0228             case value_t::discarded:
0229             default:
0230             {
0231                 m_it.primitive_iterator.set_begin();
0232                 break;
0233             }
0234         }
0235     }
0236 
0237     /*!
0238     @brief set the iterator past the last value
0239     @pre The iterator is initialized; i.e. `m_object != nullptr`.
0240     */
0241     void set_end() noexcept
0242     {
0243         JSON_ASSERT(m_object != nullptr);
0244 
0245         switch (m_object->m_data.m_type)
0246         {
0247             case value_t::object:
0248             {
0249                 m_it.object_iterator = m_object->m_data.m_value.object->end();
0250                 break;
0251             }
0252 
0253             case value_t::array:
0254             {
0255                 m_it.array_iterator = m_object->m_data.m_value.array->end();
0256                 break;
0257             }
0258 
0259             case value_t::null:
0260             case value_t::string:
0261             case value_t::boolean:
0262             case value_t::number_integer:
0263             case value_t::number_unsigned:
0264             case value_t::number_float:
0265             case value_t::binary:
0266             case value_t::discarded:
0267             default:
0268             {
0269                 m_it.primitive_iterator.set_end();
0270                 break;
0271             }
0272         }
0273     }
0274 
0275   public:
0276     /*!
0277     @brief return a reference to the value pointed to by the iterator
0278     @pre The iterator is initialized; i.e. `m_object != nullptr`.
0279     */
0280     reference operator*() const
0281     {
0282         JSON_ASSERT(m_object != nullptr);
0283 
0284         switch (m_object->m_data.m_type)
0285         {
0286             case value_t::object:
0287             {
0288                 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
0289                 return m_it.object_iterator->second;
0290             }
0291 
0292             case value_t::array:
0293             {
0294                 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
0295                 return *m_it.array_iterator;
0296             }
0297 
0298             case value_t::null:
0299                 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
0300 
0301             case value_t::string:
0302             case value_t::boolean:
0303             case value_t::number_integer:
0304             case value_t::number_unsigned:
0305             case value_t::number_float:
0306             case value_t::binary:
0307             case value_t::discarded:
0308             default:
0309             {
0310                 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
0311                 {
0312                     return *m_object;
0313                 }
0314 
0315                 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
0316             }
0317         }
0318     }
0319 
0320     /*!
0321     @brief dereference the iterator
0322     @pre The iterator is initialized; i.e. `m_object != nullptr`.
0323     */
0324     pointer operator->() const
0325     {
0326         JSON_ASSERT(m_object != nullptr);
0327 
0328         switch (m_object->m_data.m_type)
0329         {
0330             case value_t::object:
0331             {
0332                 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
0333                 return &(m_it.object_iterator->second);
0334             }
0335 
0336             case value_t::array:
0337             {
0338                 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
0339                 return &*m_it.array_iterator;
0340             }
0341 
0342             case value_t::null:
0343             case value_t::string:
0344             case value_t::boolean:
0345             case value_t::number_integer:
0346             case value_t::number_unsigned:
0347             case value_t::number_float:
0348             case value_t::binary:
0349             case value_t::discarded:
0350             default:
0351             {
0352                 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
0353                 {
0354                     return m_object;
0355                 }
0356 
0357                 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
0358             }
0359         }
0360     }
0361 
0362     /*!
0363     @brief post-increment (it++)
0364     @pre The iterator is initialized; i.e. `m_object != nullptr`.
0365     */
0366     iter_impl operator++(int)& // NOLINT(cert-dcl21-cpp)
0367     {
0368         auto result = *this;
0369         ++(*this);
0370         return result;
0371     }
0372 
0373     /*!
0374     @brief pre-increment (++it)
0375     @pre The iterator is initialized; i.e. `m_object != nullptr`.
0376     */
0377     iter_impl& operator++()
0378     {
0379         JSON_ASSERT(m_object != nullptr);
0380 
0381         switch (m_object->m_data.m_type)
0382         {
0383             case value_t::object:
0384             {
0385                 std::advance(m_it.object_iterator, 1);
0386                 break;
0387             }
0388 
0389             case value_t::array:
0390             {
0391                 std::advance(m_it.array_iterator, 1);
0392                 break;
0393             }
0394 
0395             case value_t::null:
0396             case value_t::string:
0397             case value_t::boolean:
0398             case value_t::number_integer:
0399             case value_t::number_unsigned:
0400             case value_t::number_float:
0401             case value_t::binary:
0402             case value_t::discarded:
0403             default:
0404             {
0405                 ++m_it.primitive_iterator;
0406                 break;
0407             }
0408         }
0409 
0410         return *this;
0411     }
0412 
0413     /*!
0414     @brief post-decrement (it--)
0415     @pre The iterator is initialized; i.e. `m_object != nullptr`.
0416     */
0417     iter_impl operator--(int)& // NOLINT(cert-dcl21-cpp)
0418     {
0419         auto result = *this;
0420         --(*this);
0421         return result;
0422     }
0423 
0424     /*!
0425     @brief pre-decrement (--it)
0426     @pre The iterator is initialized; i.e. `m_object != nullptr`.
0427     */
0428     iter_impl& operator--()
0429     {
0430         JSON_ASSERT(m_object != nullptr);
0431 
0432         switch (m_object->m_data.m_type)
0433         {
0434             case value_t::object:
0435             {
0436                 std::advance(m_it.object_iterator, -1);
0437                 break;
0438             }
0439 
0440             case value_t::array:
0441             {
0442                 std::advance(m_it.array_iterator, -1);
0443                 break;
0444             }
0445 
0446             case value_t::null:
0447             case value_t::string:
0448             case value_t::boolean:
0449             case value_t::number_integer:
0450             case value_t::number_unsigned:
0451             case value_t::number_float:
0452             case value_t::binary:
0453             case value_t::discarded:
0454             default:
0455             {
0456                 --m_it.primitive_iterator;
0457                 break;
0458             }
0459         }
0460 
0461         return *this;
0462     }
0463 
0464     /*!
0465     @brief comparison: equal
0466     @pre The iterator is initialized; i.e. `m_object != nullptr`.
0467     */
0468     template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
0469     bool operator==(const IterImpl& other) const
0470     {
0471         // if objects are not the same, the comparison is undefined
0472         if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
0473         {
0474             JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
0475         }
0476 
0477         JSON_ASSERT(m_object != nullptr);
0478 
0479         switch (m_object->m_data.m_type)
0480         {
0481             case value_t::object:
0482                 return (m_it.object_iterator == other.m_it.object_iterator);
0483 
0484             case value_t::array:
0485                 return (m_it.array_iterator == other.m_it.array_iterator);
0486 
0487             case value_t::null:
0488             case value_t::string:
0489             case value_t::boolean:
0490             case value_t::number_integer:
0491             case value_t::number_unsigned:
0492             case value_t::number_float:
0493             case value_t::binary:
0494             case value_t::discarded:
0495             default:
0496                 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
0497         }
0498     }
0499 
0500     /*!
0501     @brief comparison: not equal
0502     @pre The iterator is initialized; i.e. `m_object != nullptr`.
0503     */
0504     template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
0505     bool operator!=(const IterImpl& other) const
0506     {
0507         return !operator==(other);
0508     }
0509 
0510     /*!
0511     @brief comparison: smaller
0512     @pre The iterator is initialized; i.e. `m_object != nullptr`.
0513     */
0514     bool operator<(const iter_impl& other) const
0515     {
0516         // if objects are not the same, the comparison is undefined
0517         if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
0518         {
0519             JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
0520         }
0521 
0522         JSON_ASSERT(m_object != nullptr);
0523 
0524         switch (m_object->m_data.m_type)
0525         {
0526             case value_t::object:
0527                 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object));
0528 
0529             case value_t::array:
0530                 return (m_it.array_iterator < other.m_it.array_iterator);
0531 
0532             case value_t::null:
0533             case value_t::string:
0534             case value_t::boolean:
0535             case value_t::number_integer:
0536             case value_t::number_unsigned:
0537             case value_t::number_float:
0538             case value_t::binary:
0539             case value_t::discarded:
0540             default:
0541                 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
0542         }
0543     }
0544 
0545     /*!
0546     @brief comparison: less than or equal
0547     @pre The iterator is initialized; i.e. `m_object != nullptr`.
0548     */
0549     bool operator<=(const iter_impl& other) const
0550     {
0551         return !other.operator < (*this);
0552     }
0553 
0554     /*!
0555     @brief comparison: greater than
0556     @pre The iterator is initialized; i.e. `m_object != nullptr`.
0557     */
0558     bool operator>(const iter_impl& other) const
0559     {
0560         return !operator<=(other);
0561     }
0562 
0563     /*!
0564     @brief comparison: greater than or equal
0565     @pre The iterator is initialized; i.e. `m_object != nullptr`.
0566     */
0567     bool operator>=(const iter_impl& other) const
0568     {
0569         return !operator<(other);
0570     }
0571 
0572     /*!
0573     @brief add to iterator
0574     @pre The iterator is initialized; i.e. `m_object != nullptr`.
0575     */
0576     iter_impl& operator+=(difference_type i)
0577     {
0578         JSON_ASSERT(m_object != nullptr);
0579 
0580         switch (m_object->m_data.m_type)
0581         {
0582             case value_t::object:
0583                 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
0584 
0585             case value_t::array:
0586             {
0587                 std::advance(m_it.array_iterator, i);
0588                 break;
0589             }
0590 
0591             case value_t::null:
0592             case value_t::string:
0593             case value_t::boolean:
0594             case value_t::number_integer:
0595             case value_t::number_unsigned:
0596             case value_t::number_float:
0597             case value_t::binary:
0598             case value_t::discarded:
0599             default:
0600             {
0601                 m_it.primitive_iterator += i;
0602                 break;
0603             }
0604         }
0605 
0606         return *this;
0607     }
0608 
0609     /*!
0610     @brief subtract from iterator
0611     @pre The iterator is initialized; i.e. `m_object != nullptr`.
0612     */
0613     iter_impl& operator-=(difference_type i)
0614     {
0615         return operator+=(-i);
0616     }
0617 
0618     /*!
0619     @brief add to iterator
0620     @pre The iterator is initialized; i.e. `m_object != nullptr`.
0621     */
0622     iter_impl operator+(difference_type i) const
0623     {
0624         auto result = *this;
0625         result += i;
0626         return result;
0627     }
0628 
0629     /*!
0630     @brief addition of distance and iterator
0631     @pre The iterator is initialized; i.e. `m_object != nullptr`.
0632     */
0633     friend iter_impl operator+(difference_type i, const iter_impl& it)
0634     {
0635         auto result = it;
0636         result += i;
0637         return result;
0638     }
0639 
0640     /*!
0641     @brief subtract from iterator
0642     @pre The iterator is initialized; i.e. `m_object != nullptr`.
0643     */
0644     iter_impl operator-(difference_type i) const
0645     {
0646         auto result = *this;
0647         result -= i;
0648         return result;
0649     }
0650 
0651     /*!
0652     @brief return difference
0653     @pre The iterator is initialized; i.e. `m_object != nullptr`.
0654     */
0655     difference_type operator-(const iter_impl& other) const
0656     {
0657         JSON_ASSERT(m_object != nullptr);
0658 
0659         switch (m_object->m_data.m_type)
0660         {
0661             case value_t::object:
0662                 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
0663 
0664             case value_t::array:
0665                 return m_it.array_iterator - other.m_it.array_iterator;
0666 
0667             case value_t::null:
0668             case value_t::string:
0669             case value_t::boolean:
0670             case value_t::number_integer:
0671             case value_t::number_unsigned:
0672             case value_t::number_float:
0673             case value_t::binary:
0674             case value_t::discarded:
0675             default:
0676                 return m_it.primitive_iterator - other.m_it.primitive_iterator;
0677         }
0678     }
0679 
0680     /*!
0681     @brief access to successor
0682     @pre The iterator is initialized; i.e. `m_object != nullptr`.
0683     */
0684     reference operator[](difference_type n) const
0685     {
0686         JSON_ASSERT(m_object != nullptr);
0687 
0688         switch (m_object->m_data.m_type)
0689         {
0690             case value_t::object:
0691                 JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object));
0692 
0693             case value_t::array:
0694                 return *std::next(m_it.array_iterator, n);
0695 
0696             case value_t::null:
0697                 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
0698 
0699             case value_t::string:
0700             case value_t::boolean:
0701             case value_t::number_integer:
0702             case value_t::number_unsigned:
0703             case value_t::number_float:
0704             case value_t::binary:
0705             case value_t::discarded:
0706             default:
0707             {
0708                 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n))
0709                 {
0710                     return *m_object;
0711                 }
0712 
0713                 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
0714             }
0715         }
0716     }
0717 
0718     /*!
0719     @brief return the key of an object iterator
0720     @pre The iterator is initialized; i.e. `m_object != nullptr`.
0721     */
0722     const typename object_t::key_type& key() const
0723     {
0724         JSON_ASSERT(m_object != nullptr);
0725 
0726         if (JSON_HEDLEY_LIKELY(m_object->is_object()))
0727         {
0728             return m_it.object_iterator->first;
0729         }
0730 
0731         JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", m_object));
0732     }
0733 
0734     /*!
0735     @brief return the value of an iterator
0736     @pre The iterator is initialized; i.e. `m_object != nullptr`.
0737     */
0738     reference value() const
0739     {
0740         return operator*();
0741     }
0742 
0743   JSON_PRIVATE_UNLESS_TESTED:
0744     /// associated JSON instance
0745     pointer m_object = nullptr;
0746     /// the actual iterator of the associated instance
0747     internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it {};
0748 };
0749 
0750 }  // namespace detail
0751 NLOHMANN_JSON_NAMESPACE_END