// iterator standard header

// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#ifndef _ITERATOR_
#define _ITERATOR_
#include <yvals_core.h>
#if _STL_COMPILER_PREPROCESSOR
#include <iosfwd>
#include <xutility>

#pragma pack(push, _CRT_PACKING)
#pragma warning(push, _STL_WARNING_LEVEL)
#pragma warning(disable : _STL_DISABLED_WARNINGS)
_STL_DISABLE_CLANG_WARNINGS
#pragma push_macro("new")
#undef new

_STD_BEGIN
_EXPORT_STD template <class _Container>
class back_insert_iterator { // wrap pushes to back of container as output iterator
public:
    using iterator_category = output_iterator_tag;
    using value_type        = void;
    using pointer           = void;
    using reference         = void;

    using container_type = _Container;

#if _HAS_CXX20
    using difference_type = ptrdiff_t;
#else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv
    using difference_type = void;
#endif // ^^^ !_HAS_CXX20 ^^^

    _CONSTEXPR20 explicit back_insert_iterator(_Container& _Cont) noexcept /* strengthened */
        : container(_STD addressof(_Cont)) {}

    _CONSTEXPR20 back_insert_iterator& operator=(const typename _Container::value_type& _Val) {
        container->push_back(_Val);
        return *this;
    }

    _CONSTEXPR20 back_insert_iterator& operator=(typename _Container::value_type&& _Val) {
        container->push_back(_STD move(_Val));
        return *this;
    }

    _NODISCARD _CONSTEXPR20 back_insert_iterator& operator*() noexcept /* strengthened */ {
        return *this;
    }

    _CONSTEXPR20 back_insert_iterator& operator++() noexcept /* strengthened */ {
        return *this;
    }

    _CONSTEXPR20 back_insert_iterator operator++(int) noexcept /* strengthened */ {
        return *this;
    }

protected:
    _Container* container;
};

_EXPORT_STD template <class _Container>
_NODISCARD _CONSTEXPR20 back_insert_iterator<_Container> back_inserter(_Container& _Cont) noexcept /* strengthened */ {
    // return a back_insert_iterator
    return back_insert_iterator<_Container>(_Cont);
}

_EXPORT_STD template <class _Container>
class front_insert_iterator { // wrap pushes to front of container as output iterator
public:
    using iterator_category = output_iterator_tag;
    using value_type        = void;
    using pointer           = void;
    using reference         = void;

    using container_type = _Container;

#if _HAS_CXX20
    using difference_type = ptrdiff_t;
#else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv
    using difference_type = void;
#endif // ^^^ !_HAS_CXX20 ^^^

    _CONSTEXPR20 explicit front_insert_iterator(_Container& _Cont) : container(_STD addressof(_Cont)) {}

    _CONSTEXPR20 front_insert_iterator& operator=(const typename _Container::value_type& _Val) {
        // push value into container
        container->push_front(_Val);
        return *this;
    }

    _CONSTEXPR20 front_insert_iterator& operator=(typename _Container::value_type&& _Val) { // push value into container
        container->push_front(_STD move(_Val));
        return *this;
    }

    _NODISCARD _CONSTEXPR20 front_insert_iterator& operator*() { // pretend to return designated value
        return *this;
    }

    _CONSTEXPR20 front_insert_iterator& operator++() { // pretend to preincrement
        return *this;
    }

    _CONSTEXPR20 front_insert_iterator operator++(int) { // pretend to postincrement
        return *this;
    }

protected:
    _Container* container;
};

_EXPORT_STD template <class _Container>
_NODISCARD _CONSTEXPR20 front_insert_iterator<_Container> front_inserter(_Container& _Cont) {
    return front_insert_iterator<_Container>(_Cont);
}

_EXPORT_STD template <class _Container>
class insert_iterator { // wrap inserts into container as output iterator
public:
    using iterator_category = output_iterator_tag;
    using value_type        = void;
    using pointer           = void;
    using reference         = void;

    using container_type = _Container;
#if _HAS_CXX20
    using difference_type = ptrdiff_t;
    using _Wrapped_iter   = ranges::iterator_t<_Container>;
#else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv
    using difference_type = void;
    using _Wrapped_iter   = typename _Container::iterator;
#endif // ^^^ !_HAS_CXX20 ^^^

    _CONSTEXPR20 insert_iterator(_Container& _Cont, _Wrapped_iter _Where)
        : container(_STD addressof(_Cont)), iter(_STD move(_Where)) {}

    _CONSTEXPR20 insert_iterator& operator=(const typename _Container::value_type& _Val) {
        // insert into container and increment stored iterator
        iter = container->insert(iter, _Val);
        ++iter;
        return *this;
    }

    _CONSTEXPR20 insert_iterator& operator=(typename _Container::value_type&& _Val) { // push value into container
        iter = container->insert(iter, _STD move(_Val));
        ++iter;
        return *this;
    }

    _NODISCARD _CONSTEXPR20 insert_iterator& operator*() { // pretend to return designated value
        return *this;
    }

    _CONSTEXPR20 insert_iterator& operator++() { // pretend to preincrement
        return *this;
    }

    _CONSTEXPR20 insert_iterator& operator++(int) { // pretend to postincrement
        return *this;
    }

protected:
    _Container* container;
    _Wrapped_iter iter;
};

#if !_HAS_CXX20
template <class _Container>
_NODISCARD _CONSTEXPR20 insert_iterator<_Container> inserter(_Container& _Cont, typename _Container::iterator _Where) {
    return insert_iterator<_Container>(_Cont, _Where);
}
#else // ^^^ !_HAS_CXX20 / _HAS_CXX20 vvv
_EXPORT_STD template <class _Container>
_NODISCARD constexpr insert_iterator<_Container> inserter(_Container& _Cont, _RANGES iterator_t<_Container> _Where) {
    return insert_iterator<_Container>(_Cont, _Where);
}

_EXPORT_STD template <semiregular _Se>
class move_sentinel {
public:
    constexpr move_sentinel() = default;

    constexpr explicit move_sentinel(_Se _Val) noexcept(is_nothrow_move_constructible_v<_Se>) // strengthened
        : _Last(_STD move(_Val)) {}

    template <class _Se2>
        requires convertible_to<const _Se2&, _Se>
    constexpr move_sentinel(const move_sentinel<_Se2>& _Val)
        noexcept(is_nothrow_constructible_v<_Se, const _Se2&>) // strengthened
        : _Last(_Val._Get_last()) {}

    template <class _Se2>
        requires assignable_from<_Se&, const _Se2&>
    constexpr move_sentinel& operator=(const move_sentinel<_Se2>& _Val)
        noexcept(is_nothrow_assignable_v<_Se&, const _Se2&>) /* strengthened */ {
        _Last = _Val._Get_last();
        return *this;
    }

    _NODISCARD constexpr _Se base() const noexcept(is_nothrow_copy_constructible_v<_Se>) /* strengthened */ {
        return _Last;
    }

    _NODISCARD constexpr const _Se& _Get_last() const noexcept {
        return _Last;
    }

    using _Prevent_inheriting_unwrap = move_sentinel;

    _NODISCARD constexpr move_sentinel<_Unwrapped_t<const _Se&>> _Unwrapped() const& noexcept(
        noexcept(move_sentinel<_Unwrapped_t<const _Se&>>{_Last._Unwrapped()}))
        requires (_RANGES _Weakly_unwrappable_sentinel<_Se>)
    {
        return move_sentinel<_Unwrapped_t<const _Se&>>{_Last._Unwrapped()};
    }
    _NODISCARD constexpr move_sentinel<_Unwrapped_t<_Se>> _Unwrapped() && noexcept(
        noexcept(move_sentinel<_Unwrapped_t<_Se>>{_STD move(_Last)._Unwrapped()}))
        requires (_RANGES _Weakly_unwrappable_sentinel<_Se>)
    {
        return move_sentinel<_Unwrapped_t<_Se>>{_STD move(_Last)._Unwrapped()};
    }

private:
    _Se _Last{};
};
#endif // ^^^ _HAS_CXX20 ^^^

_EXPORT_STD template <class _Ty, class _Elem = char, class _Traits = char_traits<_Elem>, class _Diff = ptrdiff_t>
class istream_iterator {
public:
    using iterator_category = input_iterator_tag;
    using value_type        = _Ty;
    using difference_type   = _Diff;
    using pointer           = const _Ty*;
    using reference         = const _Ty&;
    using char_type         = _Elem;
    using traits_type       = _Traits;
    using istream_type      = basic_istream<_Elem, _Traits>;

    static_assert(conjunction_v<is_default_constructible<_Ty>, is_copy_constructible<_Ty>, is_copy_assignable<_Ty>>,
        "istream_iterator<T> requires T to be default constructible, copy constructible, and copy assignable. "
        "(N4950 [istream.iterator]/2)");

    constexpr istream_iterator() noexcept(is_nothrow_default_constructible_v<_Ty>) /* strengthened */ {}

#if _HAS_CXX20
    constexpr istream_iterator(default_sentinel_t)
        noexcept(is_nothrow_default_constructible_v<_Ty>) /* strengthened */ {}
#endif // _HAS_CXX20

    istream_iterator(istream_type& _Istr) : _Myistr(_STD addressof(_Istr)) {
        _Getval();
    }

    _NODISCARD const _Ty& operator*() const noexcept /* strengthened */ {
        _STL_ASSERT(_Myistr, "The stored stream pointer in_stream must be non-null");
        return _Myval;
    }

    _NODISCARD const _Ty* operator->() const noexcept /* strengthened */ {
        _STL_ASSERT(_Myistr, "The stored stream pointer in_stream must be non-null");
        return _STD addressof(_Myval);
    }

    istream_iterator& operator++() {
        _Getval();
        return *this;
    }

    istream_iterator operator++(int) {
        istream_iterator _Tmp = *this;
        _Getval();
        return _Tmp;
    }

    _NODISCARD bool _Equal(const istream_iterator& _Right) const noexcept {
        return _Myistr == _Right._Myistr;
    }

#if _HAS_CXX20
    _NODISCARD friend bool operator==(const istream_iterator& _Left, default_sentinel_t) noexcept /* strengthened */ {
        return !_Left._Myistr;
    }
#endif // _HAS_CXX20

private:
    void _Getval() { // get a _Ty value if possible
        _STL_ASSERT(_Myistr, "The stored stream pointer in_stream must be non-null");
        if (!(*_Myistr >> _Myval)) {
            _Myistr = nullptr;
        }
    }

    istream_type* _Myistr{nullptr}; // pointer to input stream
    _Ty _Myval{}; // lookahead value (valid if _Myistr is not null)
};

_EXPORT_STD template <class _Ty, class _Elem, class _Traits, class _Diff>
_NODISCARD bool operator==(const istream_iterator<_Ty, _Elem, _Traits, _Diff>& _Left,
    const istream_iterator<_Ty, _Elem, _Traits, _Diff>& _Right) noexcept /* strengthened */ {
    return _Left._Equal(_Right);
}

#if !_HAS_CXX20
template <class _Ty, class _Elem, class _Traits, class _Diff>
_NODISCARD bool operator!=(const istream_iterator<_Ty, _Elem, _Traits, _Diff>& _Left,
    const istream_iterator<_Ty, _Elem, _Traits, _Diff>& _Right) noexcept /* strengthened */ {
    return !(_Left == _Right);
}
#endif // !_HAS_CXX20

_EXPORT_STD template <class _Ty, class _Elem = char, class _Traits = char_traits<_Elem>>
class ostream_iterator {
public:
    using iterator_category = output_iterator_tag;
    using value_type        = void;
#if _HAS_CXX20
    using difference_type = ptrdiff_t;
#else
    using difference_type = void;
#endif
    using pointer      = void;
    using reference    = void;
    using char_type    = _Elem;
    using traits_type  = _Traits;
    using ostream_type = basic_ostream<_Elem, _Traits>;

    ostream_iterator(ostream_type& _Ostr, const _Elem* const _Delim = nullptr) noexcept /* strengthened */
        : _Mydelim(_Delim), _Myostr(_STD addressof(_Ostr)) {}

    ostream_iterator& operator=(const _Ty& _Val) { // insert value into output stream, followed by delimiter
        *_Myostr << _Val;
        if (_Mydelim) {
            *_Myostr << _Mydelim;
        }

        return *this;
    }

    _NODISCARD ostream_iterator& operator*() noexcept /* strengthened */ {
        return *this;
    }

    ostream_iterator& operator++() noexcept /* strengthened */ {
        return *this;
    }

    ostream_iterator& operator++(int) noexcept /* strengthened */ {
        return *this;
    }

private:
    const _Elem* _Mydelim; // pointer to delimiter string (NB: not freed)
    ostream_type* _Myostr; // pointer to output stream
};

_EXPORT_STD template <class _Elem, class _Traits>
class istreambuf_iterator {
public:
    using iterator_category = input_iterator_tag;
    using value_type        = _Elem;
    using difference_type   = typename _Traits::off_type;
    using pointer           = const _Elem*;
    using reference         = _Elem;
    using char_type         = _Elem;
    using traits_type       = _Traits;
    using int_type          = typename traits_type::int_type;
    using streambuf_type    = basic_streambuf<_Elem, _Traits>;
    using istream_type      = basic_istream<_Elem, _Traits>;

    constexpr istreambuf_iterator() noexcept : _Strbuf(nullptr), _Got(true), _Val() {}
#if _HAS_CXX20
    constexpr istreambuf_iterator(default_sentinel_t) noexcept : _Strbuf(nullptr), _Got(true), _Val() {}
#endif // _HAS_CXX20

    istreambuf_iterator(istream_type& _Istr) noexcept : _Strbuf(_Istr.rdbuf()), _Got(!_Strbuf), _Val() {}

    istreambuf_iterator(streambuf_type* _Sb) noexcept : _Strbuf(_Sb), _Got(!_Sb), _Val() {}

private:
    class _Istreambuf_proxy {
    public:
        _NODISCARD _Elem operator*() const noexcept(is_nothrow_copy_constructible_v<_Elem>) /* strengthened */ {
            return _Keep;
        }

    private:
        friend istreambuf_iterator;
        _Istreambuf_proxy(streambuf_type* _Strbuf_, _Elem _Keep_)
            noexcept(is_nothrow_copy_constructible_v<_Elem>) // strengthened
            : _Strbuf(_Strbuf_), _Keep(_Keep_) {}

        streambuf_type* _Strbuf;
        _Elem _Keep;
    };

public:
    istreambuf_iterator(const _Istreambuf_proxy& _Px) noexcept : _Strbuf(_Px._Strbuf), _Got(!_Strbuf), _Val() {}

    _NODISCARD _Elem operator*() const {
        if (!_Got) {
            _Peek();
        }

#if _ITERATOR_DEBUG_LEVEL == 2
        _STL_VERIFY(_Strbuf, "istreambuf_iterator is not dereferenceable");
#endif // _ITERATOR_DEBUG_LEVEL == 2

        return _Val;
    }

    istreambuf_iterator& operator++() {
#if _ITERATOR_DEBUG_LEVEL == 2
        _STL_VERIFY(_Strbuf, "istreambuf_iterator is not incrementable");
#endif // _ITERATOR_DEBUG_LEVEL == 2

        _Inc();
        return *this;
    }

    _Istreambuf_proxy operator++(int) {
        if (!_Got) {
            _Peek();
        }

        _Istreambuf_proxy _Tmp{_Strbuf, _Val};
        ++*this;
        return _Tmp;
    }

    _NODISCARD bool equal(const istreambuf_iterator& _Right) const {
        if (!_Got) {
            _Peek();
        }

        if (!_Right._Got) {
            _Right._Peek();
        }

        return (!_Strbuf && !_Right._Strbuf) || (_Strbuf && _Right._Strbuf);
    }

#if _HAS_CXX20
    _NODISCARD friend bool operator==(const istreambuf_iterator& _Left, default_sentinel_t) {
        if (!_Left._Got) {
            _Left._Peek();
        }

        return !_Left._Strbuf;
    }
#endif // _HAS_CXX20

private:
    void _Inc() { // skip to next input element
        if (!_Strbuf || traits_type::eq_int_type(traits_type::eof(), _Strbuf->sbumpc())) {
            _Strbuf = nullptr;
            _Got    = true;
        } else {
            _Got = false;
        }
    }

    _Elem _Peek() const { // peek at next input element
        int_type _Meta;
        if (!_Strbuf || traits_type::eq_int_type(traits_type::eof(), _Meta = _Strbuf->sgetc())) {
            _Strbuf = nullptr;
        } else {
            _Val = traits_type::to_char_type(_Meta);
        }

        _Got = true;
        return _Val;
    }

    mutable streambuf_type* _Strbuf; // the wrapped stream buffer
    mutable bool _Got; // true if _Val is valid
    mutable _Elem _Val; // next element to deliver
};

_EXPORT_STD template <class _Elem, class _Traits>
_NODISCARD bool operator==(
    const istreambuf_iterator<_Elem, _Traits>& _Left, const istreambuf_iterator<_Elem, _Traits>& _Right) {
    return _Left.equal(_Right);
}

#if !_HAS_CXX20
template <class _Elem, class _Traits>
_NODISCARD bool operator!=(
    const istreambuf_iterator<_Elem, _Traits>& _Left, const istreambuf_iterator<_Elem, _Traits>& _Right) {
    return !(_Left == _Right);
}
#endif // !_HAS_CXX20

#if _HAS_CXX20 && !defined(__clang__) && !defined(__EDG__) // TRANSITION, /permissive, avoid checking constraints
template <class _Elem, class _Traits>
constexpr bool _Iterator_is_contiguous<istreambuf_iterator<_Elem, _Traits>> = false;
#endif // ^^^ workaround ^^^

_EXPORT_STD template <class _Elem, class _Traits>
class ostreambuf_iterator {
public:
    using iterator_category = output_iterator_tag;
    using value_type        = void;
#if _HAS_CXX20
    using difference_type = ptrdiff_t;
#else
    using difference_type = void;
#endif
    using pointer        = void;
    using reference      = void;
    using char_type      = _Elem;
    using traits_type    = _Traits;
    using streambuf_type = basic_streambuf<_Elem, _Traits>;
    using ostream_type   = basic_ostream<_Elem, _Traits>;

    ostreambuf_iterator(streambuf_type* _Sb) noexcept : _Strbuf(_Sb) {}

    ostreambuf_iterator(ostream_type& _Ostr) noexcept : _Strbuf(_Ostr.rdbuf()) {}

    ostreambuf_iterator& operator=(_Elem _Right) { // store element and increment
        if (!_Strbuf || traits_type::eq_int_type(_Traits::eof(), _Strbuf->sputc(_Right))) {
            _Failed = true;
        }

        return *this;
    }

    _NODISCARD ostreambuf_iterator& operator*() noexcept /* strengthened */ {
        return *this;
    }

    ostreambuf_iterator& operator++() noexcept /* strengthened */ {
        return *this;
    }

    ostreambuf_iterator& operator++(int) noexcept /* strengthened */ {
        return *this;
    }

    _NODISCARD bool failed() const noexcept {
        return _Failed;
    }

private:
    bool _Failed = false; // true if any stores have failed
    streambuf_type* _Strbuf;
};

#if _HAS_CXX20 && !defined(__clang__) && !defined(__EDG__) // TRANSITION, /permissive, avoid checking constraints
template <class _Elem, class _Traits>
constexpr bool _Iterator_is_contiguous<ostreambuf_iterator<_Elem, _Traits>> = false;
#endif // ^^^ workaround ^^^

#if _HAS_CXX20
enum class _Variantish_state : unsigned char { _Nothing, _Holds_first, _Holds_second };

struct _Variantish_empty_tag {
    explicit _Variantish_empty_tag() = default;
};

template <class _Ty1, class _Ty2>
class _Variantish {
public:
    constexpr explicit _Variantish(_Variantish_empty_tag) noexcept : _Contains{_Variantish_state::_Nothing} {}

    constexpr _Variantish() noexcept(is_nothrow_default_constructible_v<_Ty1>)
        requires default_initializable<_Ty1>
        : _First{}, _Contains{_Variantish_state::_Holds_first} {}

    template <class... _Types>
    constexpr explicit _Variantish(in_place_type_t<_Ty1>, _Types&&... _Args)
        noexcept(is_nothrow_constructible_v<_Ty1, _Types...>)
        : _First(_STD forward<_Types>(_Args)...), _Contains{_Variantish_state::_Holds_first} {}

    template <class... _Types>
        requires _Different_from<_Ty1, _Ty2>
    constexpr explicit _Variantish(in_place_type_t<_Ty2>, _Types&&... _Args)
        noexcept(is_nothrow_constructible_v<_Ty2, _Types...>)
        : _Second(_STD forward<_Types>(_Args)...), _Contains{_Variantish_state::_Holds_second} {}

    template <class _Uty1, class _Uty2>
        requires _Different_from<_Variantish<_Uty1, _Uty2>, _Variantish>
    constexpr _Variantish(const _Variantish<_Uty1, _Uty2>& _That)
        noexcept(is_nothrow_constructible_v<_Ty1, const _Uty1&> && is_nothrow_constructible_v<_Ty2, const _Uty2&>)
        : _Contains{_That._Contains} {
        switch (_That._Contains) {
        case _Variantish_state::_Holds_first:
            _STD _Construct_in_place(_First, _That._Get_first());
            break;
        case _Variantish_state::_Holds_second:
            _STD _Construct_in_place(_Second, _That._Get_second());
            break;
        case _Variantish_state::_Nothing:
            break;
        }
    }

    constexpr _Variantish(const _Variantish&)
        requires is_trivially_copy_constructible_v<_Ty1> && is_trivially_copy_constructible_v<_Ty2>
    = default;

    constexpr _Variantish(const _Variantish& _That)
        noexcept(is_nothrow_copy_constructible_v<_Ty1> && is_nothrow_copy_constructible_v<_Ty2>)
        : _Contains{_That._Contains} {
        switch (_Contains) {
        case _Variantish_state::_Holds_first:
            _STD _Construct_in_place(_First, _That._Get_first());
            break;
        case _Variantish_state::_Holds_second:
            _STD _Construct_in_place(_Second, _That._Get_second());
            break;
        case _Variantish_state::_Nothing:
            break;
        }
    }

    constexpr _Variantish(_Variantish&&)
        requires is_trivially_move_constructible_v<_Ty1> && is_trivially_move_constructible_v<_Ty2>
    = default;

    constexpr _Variantish(_Variantish&& _That)
        noexcept(is_nothrow_move_constructible_v<_Ty1> && is_nothrow_move_constructible_v<_Ty2>)
        : _Contains{_That._Contains} {
        switch (_Contains) {
        case _Variantish_state::_Holds_first:
            _STD _Construct_in_place(_First, _STD move(_That._Get_first()));
            break;
        case _Variantish_state::_Holds_second:
            _STD _Construct_in_place(_Second, _STD move(_That._Get_second()));
            break;
        case _Variantish_state::_Nothing:
            break;
        }
    }

    constexpr ~_Variantish() {
        _Raw_clear();
    }

    constexpr ~_Variantish()
        requires is_trivially_destructible_v<_Ty1> && is_trivially_destructible_v<_Ty2>
    = default;

    constexpr _Variantish& operator=(const _Variantish&)
        requires is_trivially_destructible_v<_Ty1> && is_trivially_destructible_v<_Ty2>
                  && is_trivially_copy_constructible_v<_Ty1> && is_trivially_copy_constructible_v<_Ty2>
                  && is_trivially_copy_assignable_v<_Ty1> && is_trivially_copy_assignable_v<_Ty2>
    = default;

    constexpr _Variantish& operator=(const _Variantish& _That)
        noexcept(is_nothrow_copy_constructible_v<_Ty1> && is_nothrow_copy_constructible_v<_Ty2>
                 && is_nothrow_copy_assignable_v<_Ty1> && is_nothrow_copy_assignable_v<_Ty2>) {
        if (_Contains == _That._Contains) {
            switch (_Contains) {
            case _Variantish_state::_Holds_first:
                _Get_first() = _That._Get_first();
                break;
            case _Variantish_state::_Holds_second:
                _Get_second() = _That._Get_second();
                break;
            case _Variantish_state::_Nothing:
                break;
            }

            return *this;
        }

        _Clear();

        switch (_That._Contains) {
        case _Variantish_state::_Holds_first:
            _STD _Construct_in_place(_First, _That._Get_first());
            break;
        case _Variantish_state::_Holds_second:
            _STD _Construct_in_place(_Second, _That._Get_second());
            break;
        case _Variantish_state::_Nothing:
            break;
        }

        _Contains = _That._Contains;

        return *this;
    }

    constexpr _Variantish& operator=(_Variantish&&)
        requires is_trivially_destructible_v<_Ty1> && is_trivially_destructible_v<_Ty2>
                  && is_trivially_move_constructible_v<_Ty1> && is_trivially_move_constructible_v<_Ty2>
                  && is_trivially_move_assignable_v<_Ty1> && is_trivially_move_assignable_v<_Ty2>
    = default;

    constexpr _Variantish& operator=(_Variantish&& _That)
        noexcept(is_nothrow_move_constructible_v<_Ty1> && is_nothrow_move_constructible_v<_Ty2>
                 && is_nothrow_move_assignable_v<_Ty1> && is_nothrow_move_assignable_v<_Ty2>) {
        if (_Contains == _That._Contains) {
            switch (_Contains) {
            case _Variantish_state::_Holds_first:
                _Get_first() = _STD move(_That._Get_first());
                break;
            case _Variantish_state::_Holds_second:
                _Get_second() = _STD move(_That._Get_second());
                break;
            case _Variantish_state::_Nothing:
                break;
            }

            return *this;
        }

        _Clear();

        switch (_That._Contains) {
        case _Variantish_state::_Holds_first:
            _STD _Construct_in_place(_First, _STD move(_That._Get_first()));
            break;
        case _Variantish_state::_Holds_second:
            _STD _Construct_in_place(_Second, _STD move(_That._Get_second()));
            break;
        case _Variantish_state::_Nothing:
            break;
        }

        _Contains = _That._Contains;

        return *this;
    }

    template <class _Uty1, class _Uty2>
        requires _Different_from<_Variantish<_Uty1, _Uty2>, _Variantish>
    constexpr _Variantish& operator=(const _Variantish<_Uty1, _Uty2>& _That)
        noexcept(is_nothrow_constructible_v<_Ty1, const _Uty1&> && is_nothrow_constructible_v<_Ty2, const _Uty2&>
                 && is_nothrow_assignable_v<_Ty1&, const _Uty1&> && is_nothrow_assignable_v<_Ty2&, const _Uty2&>) {
        if (_Contains == _That._Contains) {
            switch (_Contains) {
            case _Variantish_state::_Holds_first:
                _Get_first() = _That._Get_first();
                break;
            case _Variantish_state::_Holds_second:
                _Get_second() = _That._Get_second();
                break;
            case _Variantish_state::_Nothing:
                break;
            }

            return *this;
        }

        _Clear();

        switch (_That._Contains) {
        case _Variantish_state::_Holds_first:
            _STD _Construct_in_place(_First, _That._Get_first());
            break;
        case _Variantish_state::_Holds_second:
            _STD _Construct_in_place(_Second, _That._Get_second());
            break;
        case _Variantish_state::_Nothing:
            break;
        }

        _Contains = _That._Contains;

        return *this;
    }

    friend constexpr void swap(_Variantish& _Left, _Variantish& _Right)
        noexcept(is_nothrow_move_constructible_v<_Ty1> && is_nothrow_move_constructible_v<_Ty2>
                 && is_nothrow_swappable_v<_Ty1> && is_nothrow_swappable_v<_Ty2>)
        requires (!_Is_trivially_swappable_v<_Ty1> || !_Is_trivially_swappable_v<_Ty2>)
    {
        if (_Left._Contains == _Right._Contains) {
            switch (_Left._Contains) {
            case _Variantish_state::_Holds_first:
                _RANGES swap(_Left._Get_first(), _Right._Get_first());
                break;
            case _Variantish_state::_Holds_second:
                _RANGES swap(_Left._Get_second(), _Right._Get_second());
                break;
            case _Variantish_state::_Nothing:
                break;
            }

            return;
        }

        auto _Tmp = _STD move(_Left);
        _Left     = _STD move(_Right);
        _Right    = _STD move(_Tmp);
    }

    constexpr void _Raw_clear() noexcept {
        switch (_Contains) {
        case _Variantish_state::_Holds_first:
            _First.~_Ty1();
            break;
        case _Variantish_state::_Holds_second:
            _Second.~_Ty2();
            break;
        case _Variantish_state::_Nothing:
            break;
        }
    }

    _NODISCARD constexpr _Ty1& _Get_first() noexcept {
        return _First;
    }
    _NODISCARD constexpr const _Ty1& _Get_first() const noexcept {
        return _First;
    }

    _NODISCARD constexpr _Ty2& _Get_second() noexcept {
        return _Second;
    }
    _NODISCARD constexpr const _Ty2& _Get_second() const noexcept {
        return _Second;
    }

    constexpr void _Clear() noexcept {
        _Raw_clear();
        _Contains = _Variantish_state::_Nothing;
    }

    template <class... _Types>
    constexpr void _Emplace_first(_Types&&... _Args) noexcept(is_nothrow_constructible_v<_Ty1, _Types...>) {
        _Clear();

        _STD _Construct_in_place(_First, _STD forward<_Types>(_Args)...);
        _Contains = _Variantish_state::_Holds_first;
    }

    template <class... _Types>
    constexpr void _Emplace_second(_Types&&... _Args) noexcept(is_nothrow_constructible_v<_Ty2, _Types...>) {
        _Clear();

        _STD _Construct_in_place(_Second, _STD forward<_Types>(_Args)...);
        _Contains = _Variantish_state::_Holds_second;
    }

    union {
        remove_cv_t<_Ty1> _First;
        remove_cv_t<_Ty2> _Second;
    };

    _Variantish_state _Contains;
};

template <class _Iter>
concept _Use_postfix_proxy =
    !requires(_Iter& __it) {
        { *__it++ } -> _Can_reference;
    } && indirectly_readable<_Iter> && constructible_from<iter_value_t<_Iter>, iter_reference_t<_Iter>>
    && move_constructible<iter_value_t<_Iter>>;

_EXPORT_STD template <input_or_output_iterator _Iter, sentinel_for<_Iter> _Se>
    requires (!same_as<_Iter, _Se> && copyable<_Iter>)
class common_iterator {
private:
    struct _Proxy_base {
        iter_value_t<_Iter> _Keep;

        constexpr explicit _Proxy_base(iter_reference_t<_Iter>&& _Right)
            noexcept(is_nothrow_constructible_v<iter_value_t<_Iter>, iter_reference_t<_Iter>>) // strengthened
            : _Keep(_STD forward<iter_reference_t<_Iter>>(_Right)) {}
    };

public:
    constexpr common_iterator()
        requires default_initializable<_Iter>
    = default;

    constexpr common_iterator(_Iter _Right) noexcept(is_nothrow_move_constructible_v<_Iter>) // strengthened
        : _Val{in_place_type<_Iter>, _STD move(_Right)} {}

    constexpr common_iterator(_Se _Right) noexcept(is_nothrow_move_constructible_v<_Se>) // strengthened
        : _Val{in_place_type<_Se>, _STD move(_Right)} {}

    constexpr explicit common_iterator(_Variantish_empty_tag _Tag) noexcept : _Val{_Tag} {}

    template <class _OIter, class _OSe>
        requires convertible_to<const _OIter&, _Iter> && convertible_to<const _OSe&, _Se>
    constexpr common_iterator(const common_iterator<_OIter, _OSe>& _Right)
        noexcept(is_nothrow_constructible_v<_Iter, const _OIter&>
                 && is_nothrow_constructible_v<_Se, const _OSe&>) // strengthened
        : _Val{_Right._Get_val()} {}

    template <class _OIter, class _OSe>
        requires convertible_to<const _OIter&, _Iter> && convertible_to<const _OSe&, _Se>
              && assignable_from<_Iter&, const _OIter&> && assignable_from<_Se&, const _OSe&>
    constexpr common_iterator& operator=(const common_iterator<_OIter, _OSe>& _Right)
        noexcept(is_nothrow_constructible_v<_Iter, const _OIter&> && is_nothrow_constructible_v<_Se, const _OSe&>
                 && is_nothrow_assignable_v<_Iter&, const _OIter&>
                 && is_nothrow_assignable_v<_Se&, const _OSe&>) /* strengthened */ {
        _Val = _Right._Get_val();
        return *this;
    }

    _NODISCARD constexpr decltype(auto) operator*() {
#if _ITERATOR_DEBUG_LEVEL != 0
        _STL_VERIFY(_Val._Contains == _Variantish_state::_Holds_first,
            "common_iterator can only be dereferenced if it holds an iterator");
#endif // _ITERATOR_DEBUG_LEVEL != 0
        return *_Val._Get_first();
    }

    _NODISCARD constexpr decltype(auto) operator*() const
        requires _Dereferenceable<const _Iter>
    {
#if _ITERATOR_DEBUG_LEVEL != 0
        _STL_VERIFY(_Val._Contains == _Variantish_state::_Holds_first,
            "common_iterator can only be dereferenced if it holds an iterator");
#endif // _ITERATOR_DEBUG_LEVEL != 0
        return *_Val._Get_first();
    }

    _NODISCARD constexpr auto operator->() const
        requires indirectly_readable<const _Iter>
              && (_Has_member_arrow<const _Iter&> || is_reference_v<iter_reference_t<_Iter>>
                  || constructible_from<iter_value_t<_Iter>, iter_reference_t<_Iter>>)
    {
#if _ITERATOR_DEBUG_LEVEL != 0
        _STL_VERIFY(_Val._Contains == _Variantish_state::_Holds_first,
            "common_iterator can only be dereferenced if it holds an iterator");
#endif // _ITERATOR_DEBUG_LEVEL != 0
        if constexpr (_Has_member_arrow<const _Iter&> || is_pointer_v<_Iter>) {
            return _Val._Get_first();
        } else if constexpr (is_reference_v<iter_reference_t<_Iter>>) {
            auto&& _Tmp = *_Val._Get_first();
            return _STD addressof(_Tmp);
        } else {
            class _Arrow_proxy : private _Proxy_base {
            public:
                friend common_iterator;

                using _Proxy_base::_Proxy_base;

                _NODISCARD constexpr const iter_value_t<_Iter>* operator->() const noexcept {
                    return _STD addressof(this->_Keep);
                }
            };

            return _Arrow_proxy{*_Val._Get_first()};
        }
    }

    constexpr common_iterator& operator++() {
#if _ITERATOR_DEBUG_LEVEL != 0
        _STL_VERIFY(_Val._Contains == _Variantish_state::_Holds_first,
            "common_iterator can only be incremented if it holds an iterator");
#endif // _ITERATOR_DEBUG_LEVEL != 0
        ++_Val._Get_first();
        return *this;
    }

    constexpr decltype(auto) operator++(int) {
#if _ITERATOR_DEBUG_LEVEL != 0
        _STL_VERIFY(_Val._Contains == _Variantish_state::_Holds_first,
            "common_iterator can only be incremented if it holds an iterator");
#endif // _ITERATOR_DEBUG_LEVEL != 0
        if constexpr (forward_iterator<_Iter>) {
            common_iterator _Tmp = *this;
            ++_Val._Get_first();
            return _Tmp;
        } else if constexpr (_Use_postfix_proxy<_Iter>) {
            class _Postfix_proxy : private _Proxy_base {
            public:
                friend common_iterator;

                using _Proxy_base::_Proxy_base;

                _NODISCARD constexpr const iter_value_t<_Iter>& operator*() const noexcept {
                    return this->_Keep;
                }
            };

            _Postfix_proxy _Tmp{*_Val._Get_first()};
            ++_Val._Get_first();
            return _Tmp;
        } else {
            return _Val._Get_first()++;
        }
    }

    template <class _OIter, sentinel_for<_Iter> _OSe>
        requires sentinel_for<_Se, _OIter>
    _NODISCARD friend constexpr bool operator==(
        const common_iterator& _Left, const common_iterator<_OIter, _OSe>& _Right) {
        auto& _Right_val = _Right._Get_val();
#if _ITERATOR_DEBUG_LEVEL != 0
        _STL_VERIFY(
            _Left._Val._Contains != _Variantish_state::_Nothing && _Right_val._Contains != _Variantish_state::_Nothing,
            "common_iterators can only be compared if both hold a value");
#endif // _ITERATOR_DEBUG_LEVEL != 0

        if (_Left._Val._Contains == _Variantish_state::_Holds_first) {
            if (_Right_val._Contains == _Variantish_state::_Holds_first) {
                if constexpr (equality_comparable_with<_Iter, _OIter>) {
                    return _Left._Val._Get_first() == _Right_val._Get_first();
                } else {
                    return true;
                }
            } else {
                return _Left._Val._Get_first() == _Right_val._Get_second();
            }
        } else {
            if (_Right_val._Contains == _Variantish_state::_Holds_first) {
                return _Left._Val._Get_second() == _Right_val._Get_first();
            } else {
                return true;
            }
        }
    }

    template <sized_sentinel_for<_Iter> _OIter, sized_sentinel_for<_Iter> _OSe>
        requires sized_sentinel_for<_Se, _OIter>
    _NODISCARD friend constexpr iter_difference_t<_OIter> operator-(
        const common_iterator& _Left, const common_iterator<_OIter, _OSe>& _Right) {
        auto& _Right_val = _Right._Get_val();
#if _ITERATOR_DEBUG_LEVEL != 0
        _STL_VERIFY(
            _Left._Val._Contains != _Variantish_state::_Nothing && _Right_val._Contains != _Variantish_state::_Nothing,
            "Cannot take difference of valueless common_iterators");
#endif // _ITERATOR_DEBUG_LEVEL != 0

        if (_Left._Val._Contains == _Variantish_state::_Holds_first) {
            if (_Right_val._Contains == _Variantish_state::_Holds_first) {
                return _Left._Val._Get_first() - _Right_val._Get_first();
            } else {
                return _Left._Val._Get_first() - _Right_val._Get_second();
            }
        } else {
            if (_Right_val._Contains == _Variantish_state::_Holds_first) {
                return _Left._Val._Get_second() - _Right_val._Get_first();
            } else {
                return 0;
            }
        }
    }

    _NODISCARD friend constexpr decltype(auto) iter_move(const common_iterator& _Right)
        noexcept(noexcept(_RANGES iter_move(_Right._Val._Get_first())))
        requires input_iterator<_Iter>
    {
#if _ITERATOR_DEBUG_LEVEL != 0
        _STL_VERIFY(_Right._Val._Contains == _Variantish_state::_Holds_first,
            "can only iter_move from common_iterator if it holds an iterator");
#endif // _ITERATOR_DEBUG_LEVEL != 0
        return _RANGES iter_move(_Right._Val._Get_first());
    }

    template <indirectly_swappable<_Iter> _OIter, class _OSe>
    friend constexpr void iter_swap(const common_iterator& _Left, const common_iterator<_OIter, _OSe>& _Right)
        noexcept(noexcept(_RANGES iter_swap(_Left._Val._Get_first(), _Right._Get_val()._Get_first()))) {
        auto& _Right_val = _Right._Get_val();
#if _ITERATOR_DEBUG_LEVEL != 0
        _STL_VERIFY(_Left._Val._Contains == _Variantish_state::_Holds_first
                        && _Right_val._Contains == _Variantish_state::_Holds_first,
            "can only iter_swap common_iterators if both hold iterators");
#endif // _ITERATOR_DEBUG_LEVEL != 0
        return _RANGES iter_swap(_Left._Val._Get_first(), _Right_val._Get_first());
    }

    _NODISCARD constexpr _Variantish<_Iter, _Se>& _Get_val() noexcept {
        return _Val;
    }
    _NODISCARD constexpr const _Variantish<_Iter, _Se>& _Get_val() const noexcept {
        return _Val;
    }

private:
    _Variantish<_Iter, _Se> _Val;
};

template <class _Iter, class _Se>
struct incrementable_traits<common_iterator<_Iter, _Se>> {
    using difference_type = iter_difference_t<_Iter>;
};

template <class, class>
struct _Common_iterator_pointer_type {
    using pointer = void;
};

template <class _Iter, class _Se>
    requires _Has_member_arrow<const common_iterator<_Iter, _Se>&>
struct _Common_iterator_pointer_type<_Iter, _Se> {
    using pointer = decltype(_STD declval<const common_iterator<_Iter, _Se>&>().operator->());
};

template <class _Iter>
concept _Has_forward_category = requires {
    typename _Iter_cat_t<_Iter>;
    requires derived_from<_Iter_cat_t<_Iter>, forward_iterator_tag>;
};

template <class _Iter>
struct _Common_iterator_category_base {};

template <class _Iter>
    requires is_integral_v<iter_difference_t<_Iter>>
struct _Common_iterator_category_base<_Iter> {
    using iterator_category = conditional_t<_Has_forward_category<_Iter>, forward_iterator_tag, input_iterator_tag>;
};

template <input_iterator _Iter, class _Se>
struct iterator_traits<common_iterator<_Iter, _Se>> : _Common_iterator_category_base<_Iter> {
    using iterator_concept = conditional_t<forward_iterator<_Iter>, forward_iterator_tag, input_iterator_tag>;
    using value_type       = iter_value_t<_Iter>;
    using difference_type  = iter_difference_t<_Iter>;
    using pointer          = _Common_iterator_pointer_type<_Iter, _Se>::pointer;
    using reference        = iter_reference_t<_Iter>;
};

template <class _Iter>
struct _Counted_iterator_value_type_base {};

template <indirectly_readable _Iter>
struct _Counted_iterator_value_type_base<_Iter> {
    using value_type = iter_value_t<_Iter>;
};

template <class _Iter>
struct _Counted_iterator_category_base : _Counted_iterator_value_type_base<_Iter> {};

template <_Has_member_iterator_category _Iter>
struct _Counted_iterator_category_base<_Iter> : _Counted_iterator_value_type_base<_Iter> {
    using iterator_category = _Iter::iterator_category;
};

template <class _Iter>
struct _Counted_iterator_concept_base : _Counted_iterator_category_base<_Iter> {};

template <_Has_member_iterator_concept _Iter>
struct _Counted_iterator_concept_base<_Iter> : _Counted_iterator_category_base<_Iter> {
    using iterator_concept = _Iter::iterator_concept;
};

_EXPORT_STD template <input_or_output_iterator _Iter>
class counted_iterator : public _Counted_iterator_concept_base<_Iter> {
public:
    using iterator_type   = _Iter;
    using difference_type = iter_difference_t<_Iter>;

    // [counted.iter.const]
    constexpr counted_iterator()
        requires default_initializable<_Iter>
    = default;

    constexpr counted_iterator(_Iter _Right, const iter_difference_t<_Iter> _Diff)
        noexcept(is_nothrow_move_constructible_v<_Iter>) // strengthened
        : _Current(_STD move(_Right)), _Length(_Diff) {
#if _ITERATOR_DEBUG_LEVEL != 0
        _STL_VERIFY(_Diff >= 0, "counted_iterator requires non-negative length n");
#endif // _ITERATOR_DEBUG_LEVEL != 0
    }

    template <class _Other>
        requires convertible_to<const _Other&, _Iter>
    constexpr counted_iterator(const counted_iterator<_Other>& _Right)
        noexcept(is_nothrow_constructible_v<_Iter, const _Other&>) // strengthened
        : _Current(_Right.base()), _Length(_Right.count()) {}

    template <class _Other>
        requires assignable_from<_Iter&, const _Other&>
    constexpr counted_iterator& operator=(const counted_iterator<_Other>& _Right)
        noexcept(is_nothrow_assignable_v<_Iter&, const _Other&>) /* strengthened */ {
        _Current = _Right.base();
        _Length  = _Right.count();
        return *this;
    }

    // [counted.iter.access]
    _NODISCARD constexpr const _Iter& base() const& noexcept {
        return _Current;
    }

    _NODISCARD constexpr _Iter base() && noexcept(is_nothrow_move_constructible_v<_Iter>) /* strengthened */ {
        return _STD move(_Current);
    }

    _NODISCARD constexpr iter_difference_t<_Iter> count() const noexcept {
        return _Length;
    }

    // [counted.iter.elem]
    _NODISCARD constexpr decltype(auto) operator*() noexcept(noexcept(*_Current)) /* strengthened */ {
#if _ITERATOR_DEBUG_LEVEL != 0
        _STL_VERIFY(_Length > 0, "counted_iterator dereference beyond end of range");
#endif // _ITERATOR_DEBUG_LEVEL != 0
        return *_Current;
    }

    _NODISCARD constexpr decltype(auto) operator*() const noexcept(noexcept(*_Current)) /* strengthened */
        requires _Dereferenceable<const _Iter>
    {
#if _ITERATOR_DEBUG_LEVEL != 0
        _STL_VERIFY(_Length > 0, "counted_iterator dereference beyond end of range");
#endif // _ITERATOR_DEBUG_LEVEL != 0
        return *_Current;
    }

    _NODISCARD constexpr auto operator->() const noexcept
        requires contiguous_iterator<_Iter>
    {
        return _STD to_address(_Current);
    }

    _NODISCARD constexpr decltype(auto) operator[](const iter_difference_t<_Iter> _Diff) const
        requires random_access_iterator<_Iter>
    {
#if _ITERATOR_DEBUG_LEVEL != 0
        _STL_VERIFY(_Diff < _Length, "counted_iterator index out of range");
#endif // _ITERATOR_DEBUG_LEVEL != 0
        return _Current[_Diff];
    }

    // [counted.iter.nav]
    constexpr counted_iterator& operator++() {
#if _ITERATOR_DEBUG_LEVEL != 0
        _STL_VERIFY(_Length > 0, "counted_iterator increment beyond end of range");
#endif // _ITERATOR_DEBUG_LEVEL != 0
        ++_Current;
        --_Length;
        return *this;
    }

    constexpr decltype(auto) operator++(int) {
#if _ITERATOR_DEBUG_LEVEL != 0
        _STL_VERIFY(_Length > 0, "counted_iterator increment beyond end of range");
#endif // _ITERATOR_DEBUG_LEVEL != 0
        --_Length;
        _TRY_BEGIN
        return _Current++;

        _CATCH_ALL
        ++_Length;

        _RERAISE;
        _CATCH_END
    }

    constexpr counted_iterator operator++(int)
        requires forward_iterator<_Iter>
    {
#if _ITERATOR_DEBUG_LEVEL != 0
        _STL_VERIFY(_Length > 0, "counted_iterator increment beyond end of range");
#endif // _ITERATOR_DEBUG_LEVEL != 0
        counted_iterator _Tmp = *this;
        ++_Current;
        --_Length;
        return _Tmp;
    }

    constexpr counted_iterator& operator--()
        requires bidirectional_iterator<_Iter>
    {
        --_Current;
        ++_Length;
        return *this;
    }

    constexpr counted_iterator operator--(int)
        requires bidirectional_iterator<_Iter>
    {
        counted_iterator _Tmp = *this;
        --_Current;
        ++_Length;
        return _Tmp;
    }

    _NODISCARD constexpr counted_iterator operator+(const iter_difference_t<_Iter> _Diff) const
        requires random_access_iterator<_Iter>
    {
        return counted_iterator{_Current + _Diff, static_cast<iter_difference_t<_Iter>>(_Length - _Diff)};
    }

    _NODISCARD friend constexpr counted_iterator operator+(
        const iter_difference_t<_Iter> _Diff, const counted_iterator& _Right)
        requires random_access_iterator<_Iter>
    {
        return counted_iterator{_Right._Current + _Diff, static_cast<iter_difference_t<_Iter>>(_Right._Length - _Diff)};
    }

    constexpr counted_iterator& operator+=(const iter_difference_t<_Iter> _Diff)
        requires random_access_iterator<_Iter>
    {
#if _ITERATOR_DEBUG_LEVEL != 0
        _STL_VERIFY(_Diff <= _Length, "counted_iterator seek beyond end of range");
#endif // _ITERATOR_DEBUG_LEVEL != 0
        _Current += _Diff;
        _Length -= _Diff;
        return *this;
    }

    _NODISCARD constexpr counted_iterator operator-(const iter_difference_t<_Iter> _Diff) const
        requires random_access_iterator<_Iter>
    {
        return counted_iterator{_Current - _Diff, static_cast<iter_difference_t<_Iter>>(_Length + _Diff)};
    }

    template <common_with<_Iter> _Other>
    _NODISCARD friend constexpr iter_difference_t<_Other> operator-(
        const counted_iterator& _Left, const counted_iterator<_Other>& _Right) noexcept /* strengthened */ {
#if _ITERATOR_DEBUG_LEVEL != 0
        _Same_sequence(_Left, _Right);
#endif // _ITERATOR_DEBUG_LEVEL != 0
        return _Right.count() - _Left._Length;
    }

    _NODISCARD friend constexpr iter_difference_t<_Iter> operator-(
        const counted_iterator& _Left, default_sentinel_t) noexcept /* strengthened */ {
        return -_Left._Length;
    }

    _NODISCARD friend constexpr iter_difference_t<_Iter> operator-(
        default_sentinel_t, const counted_iterator& _Right) noexcept /* strengthened */ {
        return _Right._Length;
    }

    constexpr counted_iterator& operator-=(const iter_difference_t<_Iter> _Diff)
        requires random_access_iterator<_Iter>
    {
#if _ITERATOR_DEBUG_LEVEL != 0
        _STL_VERIFY(-_Diff <= _Length, "counted_iterator decrement beyond end of range");
#endif // _ITERATOR_DEBUG_LEVEL != 0
        _Current -= _Diff;
        _Length += _Diff;
        return *this;
    }

    // [counted.iter.cmp]
    template <common_with<_Iter> _Other>
    _NODISCARD friend constexpr bool operator==(
        const counted_iterator& _Left, const counted_iterator<_Other>& _Right) noexcept /* strengthened */ {
#if _ITERATOR_DEBUG_LEVEL != 0
        _Same_sequence(_Left, _Right);
#endif // _ITERATOR_DEBUG_LEVEL != 0
        return _Left._Length == _Right.count();
    }

    _NODISCARD friend constexpr bool operator==(const counted_iterator& _Left, default_sentinel_t) noexcept
    /* strengthened */ {
        return _Left._Length == 0;
    }

    template <common_with<_Iter> _Other>
    _NODISCARD friend constexpr strong_ordering operator<=>(
        const counted_iterator& _Left, const counted_iterator<_Other>& _Right) noexcept /* strengthened */ {
#if _ITERATOR_DEBUG_LEVEL != 0
        _Same_sequence(_Left, _Right);
#endif // _ITERATOR_DEBUG_LEVEL != 0
        return _Right.count() <=> _Left._Length;
    }

    // [counted.iter.cust]
    _NODISCARD friend constexpr decltype(auto) iter_move(const counted_iterator& _Right)
        noexcept(noexcept(_RANGES iter_move(_Right._Current)))
        requires input_iterator<_Iter>
    {
        return _RANGES iter_move(_Right._Current);
    }

    template <indirectly_swappable<_Iter> _Other>
    friend constexpr void iter_swap(const counted_iterator& _Left, const counted_iterator<_Other>& _Right)
        noexcept(noexcept(_RANGES iter_swap(_Left._Current, _Right.base()))) {
        _RANGES iter_swap(_Left._Current, _Right.base());
    }

#if _ITERATOR_DEBUG_LEVEL != 0
    template <common_with<_Iter> _Other>
    friend constexpr void _Same_sequence(
        const counted_iterator& _Left, const counted_iterator<_Other>& _Right) noexcept {
#ifdef _M_CEE // TRANSITION, VSO-1665606
        (void) _Left;
        (void) _Right;
#else // ^^^ workaround / no workaround vvv

        // Per N4950 [counted.iterator]/3, two counted_iterators x and y refer to elements of the same sequence iff
        // for some integer n, next(x.base(), x.count() + n) and next(y.base(), y.count() + n)
        // "refer to the same (possibly past-the-end) element".
        // Iterator equality is a fair proxy for the vaguely-defined "refer to the same element".
        if constexpr (forward_iterator<_Iter> && forward_iterator<_Other>) {
            using _CIter = common_type_t<_Iter, _Other>;
            using _CDiff = common_type_t<iter_difference_t<_Iter>, iter_difference_t<_Other>>;

            const _CDiff _Diff = static_cast<_CDiff>(_Left._Length) - static_cast<_CDiff>(_Right.count());
            if (_Diff < 0) {
                _STL_VERIFY(
                    static_cast<_CIter>(_Left._Current) == _RANGES next(static_cast<_CIter>(_Right.base()), -_Diff),
                    "counted_iterators are from different ranges");
            } else {
                _STL_VERIFY(
                    _RANGES next(static_cast<_CIter>(_Left._Current), _Diff) == static_cast<_CIter>(_Right.base()),
                    "counted_iterators are from different ranges");
            }
        }
#endif // ^^^ no workaround ^^^
    }
#endif // _ITERATOR_DEBUG_LEVEL != 0

    template <common_with<_Iter> _Other>
    friend constexpr void _Verify_range(const counted_iterator& _Left, const counted_iterator<_Other>& _Right) {
        if constexpr (_Range_verifiable_v<_Iter, _Other>) {
            _Verify_range(_Left._Current, _Right.base());
        }
#if _ITERATOR_DEBUG_LEVEL != 0
        _Same_sequence(_Left, _Right);
#endif // _ITERATOR_DEBUG_LEVEL != 0
    }

    constexpr void _Verify_offset(const iter_difference_t<_Iter> _Off) const {
#if _ITERATOR_DEBUG_LEVEL != 0
        _STL_VERIFY(_Off <= _Length, "Offset larger than counted_iterator length");
#endif // _ITERATOR_DEBUG_LEVEL != 0
        if constexpr (_Offset_verifiable_v<_Iter>) {
            _Current._Verify_offset(_Off);
        }
    }

    using _Prevent_inheriting_unwrap = counted_iterator;

    _NODISCARD constexpr counted_iterator<_Unwrapped_t<const _Iter&>> _Unwrapped() const& noexcept(
        noexcept(counted_iterator<_Unwrapped_t<const _Iter&>>{_Current._Unwrapped(), _Length}))
        requires _Unwrappable_v<const _Iter&>
    {
        return counted_iterator<_Unwrapped_t<const _Iter&>>{_Current._Unwrapped(), _Length};
    }

    _NODISCARD constexpr counted_iterator<_Unwrapped_t<_Iter>> _Unwrapped() && noexcept(
        noexcept(counted_iterator<_Unwrapped_t<_Iter>>{_STD move(_Current)._Unwrapped(), _Length}))
        requires _Unwrappable_v<_Iter>
    {
        return counted_iterator<_Unwrapped_t<_Iter>>{_STD move(_Current)._Unwrapped(), _Length};
    }

    static constexpr bool _Unwrap_when_unverified = _Do_unwrap_when_unverified_v<_Iter>;

    template <class _Other>
        requires _Wrapped_seekable_v<_Iter, const _Other&>
    constexpr void _Seek_to(const counted_iterator<_Other>& _It) {
        _Current._Seek_to(_It.base());
        _Length = _It.count();
    }

    template <class _Other>
        requires _Wrapped_seekable_v<_Iter, _Other>
    constexpr void _Seek_to(counted_iterator<_Other>&& _It) {
        _Current._Seek_to(_STD move(_It).base());
        _Length = _It.count();
    }

private:
    _Iter _Current{};
    iter_difference_t<_Iter> _Length = 0;
};

template <input_iterator _Iter>
    requires (!_Is_from_primary<iterator_traits<_Iter>>)
struct iterator_traits<counted_iterator<_Iter>> : iterator_traits<_Iter> {
    using pointer = conditional_t<contiguous_iterator<_Iter>, add_pointer_t<iter_reference_t<_Iter>>, void>;
};
#endif // _HAS_CXX20

_STD_END

#pragma push_macro("stdext")
#pragma push_macro("checked_array_iterator")
#pragma push_macro("make_checked_array_iterator")
#pragma push_macro("make_unchecked_array_iterator")
#pragma push_macro("unchecked_array_iterator")
#undef stdext
#undef checked_array_iterator
#undef make_checked_array_iterator
#undef make_unchecked_array_iterator
#undef unchecked_array_iterator

_STDEXT_BEGIN
template <class _Ptr>
class _DEPRECATE_STDEXT_ARR_ITERS checked_array_iterator { // wrap a pointer with checking
private:
    using _Pointee_type = _STD remove_pointer_t<_Ptr>;
    static_assert(_STD is_pointer_v<_Ptr> && _STD is_object_v<_Pointee_type>,
        "checked_array_iterator requires pointers to objects");

public:
    using iterator_category = _STD random_access_iterator_tag;
    using value_type        = _STD remove_cv_t<_Pointee_type>;
    using difference_type   = _STD ptrdiff_t;
    using pointer           = _Ptr;
    using reference         = _Pointee_type&;
#if _HAS_CXX20
    using iterator_concept = _STD contiguous_iterator_tag;
#endif // _HAS_CXX20

    constexpr checked_array_iterator() = default;

    constexpr checked_array_iterator(const _Ptr _Array, const size_t _Size, const size_t _Index = 0) noexcept
        : _Myarray(_Array), _Mysize(_Size), _Myindex(_Index) {
        _STL_VERIFY(_Index <= _Size, "checked_array_iterator construction index out of range");
    }

    _STL_DISABLE_DEPRECATED_WARNING
    template <class _Ty = _Pointee_type, _STD enable_if_t<!_STD is_const_v<_Ty>, int> = 0>
    constexpr operator checked_array_iterator<const _Ty*>() const noexcept {
        return checked_array_iterator<const _Ty*>{_Myarray, _Mysize, _Myindex};
    }
    _STL_RESTORE_DEPRECATED_WARNING

    _NODISCARD constexpr _Ptr base() const noexcept {
        return _Myarray + _Myindex;
    }

    _NODISCARD constexpr reference operator*() const noexcept {
        return *operator->();
    }

    _NODISCARD constexpr pointer operator->() const noexcept {
        _STL_VERIFY(_Myarray, "cannot dereference value-initialized or null checked_array_iterator");
        _STL_VERIFY(_Myindex < _Mysize, "cannot dereference end checked_array_iterator");
        return _Myarray + _Myindex;
    }

    constexpr checked_array_iterator& operator++() noexcept {
        _STL_VERIFY(_Myarray, "cannot increment value-initialized or null checked_array_iterator");
        _STL_VERIFY(_Myindex < _Mysize, "cannot increment checked_array_iterator past end");
        ++_Myindex;
        return *this;
    }

    constexpr checked_array_iterator operator++(int) noexcept {
        checked_array_iterator _Tmp = *this;
        ++*this;
        return _Tmp;
    }

    constexpr checked_array_iterator& operator--() noexcept {
        _STL_VERIFY(_Myarray, "cannot decrement value-initialized or null checked_array_iterator");
        _STL_VERIFY(_Myindex != 0, "cannot decrement checked_array_iterator before begin");
        --_Myindex;
        return *this;
    }

    constexpr checked_array_iterator operator--(int) noexcept {
        checked_array_iterator _Tmp = *this;
        --*this;
        return _Tmp;
    }

    constexpr checked_array_iterator& operator+=(const difference_type _Off) noexcept {
        if (_Off != 0) {
            _STL_VERIFY(_Myarray, "cannot seek value-initialized or null checked_array_iterator");
        }

        if (_Off < 0) {
            _STL_VERIFY(
                _Myindex >= size_t{0} - static_cast<size_t>(_Off), "cannot seek checked_array_iterator before begin");
        }

        if (_Off > 0) {
            _STL_VERIFY(
                _Mysize - _Myindex >= static_cast<size_t>(_Off), "cannot seek checked_array_iterator after end");
        }

        _Myindex += _Off;
        return *this;
    }

    _NODISCARD constexpr checked_array_iterator operator+(const difference_type _Off) const noexcept {
        checked_array_iterator _Tmp = *this;
        _Tmp += _Off;
        return _Tmp;
    }

    _NODISCARD friend constexpr checked_array_iterator operator+(
        const difference_type _Off, const checked_array_iterator<_Ptr>& _Next) noexcept {
        return _Next + _Off;
    }

    constexpr checked_array_iterator& operator-=(const difference_type _Off) noexcept {
        if (_Off != 0) {
            _STL_VERIFY(_Myarray, "cannot seek value-initialized or null checked_array_iterator");
        }

        if (_Off > 0) {
            _STL_VERIFY(_Myindex >= static_cast<size_t>(_Off), "cannot seek checked_array_iterator before begin");
        }

        if (_Off < 0) {
            _STL_VERIFY(_Mysize - _Myindex >= size_t{0} - static_cast<size_t>(_Off),
                "cannot seek checked_array_iterator after end");
        }

        _Myindex -= _Off;
        return *this;
    }

    _NODISCARD constexpr checked_array_iterator operator-(const difference_type _Off) const noexcept {
        checked_array_iterator _Tmp = *this;
        _Tmp -= _Off;
        return _Tmp;
    }

    _NODISCARD constexpr difference_type operator-(const checked_array_iterator& _Right) const noexcept {
        _STL_VERIFY(_Myarray == _Right._Myarray && _Mysize == _Right._Mysize,
            "cannot subtract incompatible checked_array_iterators");
        return static_cast<difference_type>(_Myindex - _Right._Myindex);
    }

    _NODISCARD constexpr reference operator[](const difference_type _Off) const noexcept {
        return *(*this + _Off);
    }

    _NODISCARD constexpr bool operator==(const checked_array_iterator& _Right) const noexcept {
        _STL_VERIFY(_Myarray == _Right._Myarray && _Mysize == _Right._Mysize,
            "cannot compare incompatible checked_array_iterators for equality");
        return _Myindex == _Right._Myindex;
    }

#if _HAS_CXX20
    _NODISCARD constexpr _STD strong_ordering operator<=>(const checked_array_iterator& _Right) const noexcept {
        _STL_VERIFY(_Myarray == _Right._Myarray && _Mysize == _Right._Mysize,
            "cannot compare incompatible checked_array_iterators");
        return _Myindex <=> _Right._Myindex;
    }
#else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv
    _NODISCARD constexpr bool operator!=(const checked_array_iterator& _Right) const noexcept {
        return !(*this == _Right);
    }

    _NODISCARD constexpr bool operator<(const checked_array_iterator& _Right) const noexcept {
        _STL_VERIFY(_Myarray == _Right._Myarray && _Mysize == _Right._Mysize,
            "cannot compare incompatible checked_array_iterators");
        return _Myindex < _Right._Myindex;
    }

    _NODISCARD constexpr bool operator>(const checked_array_iterator& _Right) const noexcept {
        return _Right < *this;
    }

    _NODISCARD constexpr bool operator<=(const checked_array_iterator& _Right) const noexcept {
        return !(_Right < *this);
    }

    _NODISCARD constexpr bool operator>=(const checked_array_iterator& _Right) const noexcept {
        return !(*this < _Right);
    }
#endif // ^^^ !_HAS_CXX20 ^^^

    friend constexpr void _Verify_range(
        const checked_array_iterator& _First, const checked_array_iterator& _Last) noexcept {
        _STL_VERIFY(_First._Myarray == _Last._Myarray && _First._Mysize == _Last._Mysize,
            "mismatching checked_array_iterators");
        _STL_VERIFY(_First._Myindex <= _Last._Myindex, "transposed checked_array_iterator range");
    }

    constexpr void _Verify_offset(const difference_type _Off) const noexcept {
        if (_Off < 0) {
            _STL_VERIFY(_Myindex >= size_t{0} - static_cast<size_t>(_Off),
                "cannot seek checked_array_iterator iterator before begin");
        }

        if (_Off > 0) {
            _STL_VERIFY(_Mysize - _Myindex >= static_cast<size_t>(_Off),
                "cannot seek checked_array_iterator iterator after end");
        }
    }

    using _Prevent_inheriting_unwrap = checked_array_iterator;

    _NODISCARD constexpr _Ptr _Unwrapped() const noexcept {
        return _Myarray + _Myindex;
    }

    constexpr void _Seek_to(_Ptr _It) noexcept {
        _Myindex = static_cast<size_t>(_It - _Myarray);
    }

private:
    _Ptr _Myarray   = nullptr; // beginning of array
    size_t _Mysize  = 0; // size of array
    size_t _Myindex = 0; // offset into array
};

_STL_DISABLE_DEPRECATED_WARNING
template <class _Ptr>
_DEPRECATE_STDEXT_ARR_ITERS _NODISCARD constexpr checked_array_iterator<_Ptr> make_checked_array_iterator(
    const _Ptr _Array, const size_t _Size, const size_t _Index = 0) noexcept {
    return checked_array_iterator<_Ptr>(_Array, _Size, _Index);
}
_STL_RESTORE_DEPRECATED_WARNING

template <class _Ptr>
class _DEPRECATE_STDEXT_ARR_ITERS unchecked_array_iterator { // wrap a pointer without checking, to silence warnings
private:
    using _Pointee_type = _STD remove_pointer_t<_Ptr>;
    static_assert(_STD is_pointer_v<_Ptr> && _STD is_object_v<_Pointee_type>,
        "unchecked_array_iterator requires pointers to objects");

public:
    using iterator_category = _STD random_access_iterator_tag;
    using value_type        = _STD remove_cv_t<_Pointee_type>;
    using difference_type   = _STD ptrdiff_t;
    using pointer           = _Ptr;
    using reference         = _Pointee_type&;
#if _HAS_CXX20
    using iterator_concept = _STD contiguous_iterator_tag;
#endif // _HAS_CXX20

    constexpr unchecked_array_iterator() = default;

    constexpr explicit unchecked_array_iterator(const _Ptr _Src) noexcept : _Myptr(_Src) {}

    _STL_DISABLE_DEPRECATED_WARNING
    template <class _Ty = _Pointee_type, _STD enable_if_t<!_STD is_const_v<_Ty>, int> = 0>
    constexpr operator unchecked_array_iterator<const _Ty*>() const noexcept {
        return unchecked_array_iterator<const _Ty*>{_Myptr};
    }
    _STL_RESTORE_DEPRECATED_WARNING

    _NODISCARD constexpr _Ptr base() const noexcept {
        return _Myptr;
    }

    _NODISCARD constexpr reference operator*() const noexcept {
        return *_Myptr;
    }

    _NODISCARD constexpr pointer operator->() const noexcept {
        return _Myptr;
    }

    constexpr unchecked_array_iterator& operator++() noexcept {
        ++_Myptr;
        return *this;
    }

    constexpr unchecked_array_iterator operator++(int) noexcept {
        unchecked_array_iterator _Tmp = *this;
        ++_Myptr;
        return _Tmp;
    }

    constexpr unchecked_array_iterator& operator--() noexcept {
        --_Myptr;
        return *this;
    }

    constexpr unchecked_array_iterator operator--(int) noexcept {
        unchecked_array_iterator _Tmp = *this;
        --_Myptr;
        return _Tmp;
    }

    constexpr unchecked_array_iterator& operator+=(const difference_type _Off) noexcept {
        _Myptr += _Off;
        return *this;
    }

    _NODISCARD constexpr unchecked_array_iterator operator+(const difference_type _Off) const noexcept {
        unchecked_array_iterator _Tmp = *this;
        _Tmp += _Off;
        return _Tmp;
    }

    _NODISCARD friend constexpr unchecked_array_iterator operator+(
        const difference_type _Off, const unchecked_array_iterator& _Next) noexcept {
        return _Next + _Off;
    }

    constexpr unchecked_array_iterator& operator-=(const difference_type _Off) noexcept {
        return *this += -_Off;
    }

    _NODISCARD constexpr unchecked_array_iterator operator-(const difference_type _Off) const noexcept {
        unchecked_array_iterator _Tmp = *this;
        _Tmp -= _Off;
        return _Tmp;
    }

    _NODISCARD constexpr difference_type operator-(const unchecked_array_iterator& _Right) const noexcept {
        return _Myptr - _Right._Myptr;
    }

    _NODISCARD constexpr reference operator[](const difference_type _Off) const noexcept {
        return *(*this + _Off);
    }

    _NODISCARD constexpr bool operator==(const unchecked_array_iterator& _Right) const noexcept {
        return _Myptr == _Right._Myptr;
    }

#if _HAS_CXX20
    _NODISCARD constexpr _STD strong_ordering operator<=>(const unchecked_array_iterator& _Right) const noexcept {
        return _Myptr <=> _Right._Myptr;
    }
#else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv
    _NODISCARD constexpr bool operator!=(const unchecked_array_iterator& _Right) const noexcept {
        return !(*this == _Right);
    }

    _NODISCARD constexpr bool operator<(const unchecked_array_iterator& _Right) const noexcept {
        return _Myptr < _Right._Myptr;
    }

    _NODISCARD constexpr bool operator>(const unchecked_array_iterator& _Right) const noexcept {
        return _Right < *this;
    }

    _NODISCARD constexpr bool operator<=(const unchecked_array_iterator& _Right) const noexcept {
        return !(_Right < *this);
    }

    _NODISCARD constexpr bool operator>=(const unchecked_array_iterator& _Right) const noexcept {
        return !(*this < _Right);
    }
#endif // ^^^ !_HAS_CXX20 ^^^

#if _ITERATOR_DEBUG_LEVEL != 0
    friend constexpr void _Verify_range(
        const unchecked_array_iterator _First, const unchecked_array_iterator _Last) noexcept {
        _STD _Verify_range(_First._Myptr, _Last._Myptr);
    }
#endif // _ITERATOR_DEBUG_LEVEL != 0

    using _Prevent_inheriting_unwrap = unchecked_array_iterator;

    static constexpr bool _Unwrap_when_unverified = true;

    _NODISCARD constexpr _Ptr _Unwrapped() const noexcept {
        return _Myptr;
    }

    constexpr void _Seek_to(_Ptr _It) noexcept {
        _Myptr = _It;
    }

private:
    _Ptr _Myptr = nullptr; // underlying pointer
};

_STL_DISABLE_DEPRECATED_WARNING
template <class _Ptr>
_DEPRECATE_STDEXT_ARR_ITERS _NODISCARD unchecked_array_iterator<_Ptr> make_unchecked_array_iterator(
    const _Ptr _It) noexcept {
    return unchecked_array_iterator<_Ptr>(_It);
}
_STL_RESTORE_DEPRECATED_WARNING
_STDEXT_END

#if _HAS_CXX20
_STD_BEGIN
_STL_DISABLE_DEPRECATED_WARNING
template <class _Ty>
struct pointer_traits<_STDEXT checked_array_iterator<_Ty*>> {
    using pointer         = _STDEXT checked_array_iterator<_Ty*>;
    using element_type    = _Ty;
    using difference_type = ptrdiff_t;

    _NODISCARD static constexpr element_type* to_address(const pointer _Iter) noexcept {
        return _Iter._Unwrapped();
    }
};
_STL_RESTORE_DEPRECATED_WARNING
_STD_END
#endif // _HAS_CXX20

#pragma pop_macro("unchecked_array_iterator")
#pragma pop_macro("make_unchecked_array_iterator")
#pragma pop_macro("make_checked_array_iterator")
#pragma pop_macro("checked_array_iterator")
#pragma pop_macro("stdext")

#pragma pop_macro("new")
_STL_RESTORE_CLANG_WARNINGS
#pragma warning(pop)
#pragma pack(pop)
#endif // _STL_COMPILER_PREPROCESSOR
#endif // _ITERATOR_
