Skip to content

<xstd/misc/concepts/proxy_iterator.hpp>

xstd::proxy_iterator

template<class I>
concept proxy_iterator = proxy_semi_iterator<I> and proxy_reference<iter_reference_t<I>>;

An iterator whose reference is a proxy reference.

Models

  • A semi-iterator whose reference is a proxy reference models it.
  • A semi-iterator whose reference keeps the built-in address does not.

Notes

It subsumes proxy_semi_iterator<I>.

Example

#include <xstd/misc/concepts/proxy_iterator.hpp>      // proxy_iterator
#include <xstd/misc/concepts/proxy_semi_iterator.hpp> // proxy_semi_iterator
#include <array>                                      // array
#include <cstddef>                                    // ptrdiff_t
#include <iostream>                                   // boolalpha, cout
#include <type_traits>                                // is_pointer_v

enum class shade : unsigned char
{
        light,
        dark
};

class shade_iterator;

// One shade, kept as one bit of a word, and read and written through this proxy.
class shade_reference
{
        unsigned* m_word;
        unsigned m_bit;

public:
        [[nodiscard]] constexpr shade_reference(unsigned* word, unsigned bit) noexcept
                : m_word(word)
                , m_bit(bit)
        {}

        [[nodiscard]] constexpr explicit(false) operator shade() const noexcept
        {
                return static_cast<shade>((*m_word >> m_bit) & 1U);
        }

        // Writes through a const proxy, as a const language reference writes to what it refers to.
        constexpr auto operator=(shade value) const noexcept
                -> shade_reference const&
        {
                *m_word = (*m_word & ~(1U << m_bit)) | (static_cast<unsigned>(value) << m_bit);
                return *this;
        }

        // The address of a shade is an iterator that yields this proxy back.
        [[nodiscard]] constexpr auto operator&() const noexcept
                -> shade_iterator;
};

class shade_iterator
{
        unsigned* m_word;
        unsigned m_bit;

public:
        using value_type      = shade;
        using difference_type = std::ptrdiff_t;

        [[nodiscard]] constexpr shade_iterator(unsigned* word, unsigned bit) noexcept
                : m_word(word)
                , m_bit(bit)
        {}

        [[nodiscard]] constexpr auto operator*() const noexcept
                -> shade_reference
        {
                return shade_reference(m_word, m_bit);
        }
};

constexpr auto shade_reference::operator&() const noexcept
        -> shade_iterator
{
        return shade_iterator(m_word, m_bit);
}

[[nodiscard]] constexpr auto name(shade s) noexcept
        -> char const*
{
        return s == shade::dark ? "dark" : "light";
}

// The address of the element an iterator points to: for a pointer and for a proxy iterator, an iterator to it again.
template<class I>
        requires std::is_pointer_v<I> or xstd::proxy_iterator<I>
[[nodiscard]] constexpr auto address_of_element(I it)
{
        return &*it;
}

auto main() -> int
{
        auto plain = std::array<shade, 2>{shade::light, shade::light};
        auto word  = 0b00U;

        *address_of_element(&plain[1])                = shade::dark;
        *address_of_element(shade_iterator(&word, 1)) = shade::dark;
        std::cout << "plain: " << name(plain[0]) << ' ' << name(plain[1]) << '\n';
        std::cout << "packed: " << name(*shade_iterator(&word, 0)) << ' ' << name(*shade_iterator(&word, 1)) << '\n';

        std::cout << std::boolalpha;
        std::cout << "proxy_iterator<shade_iterator> is " << xstd::proxy_iterator<shade_iterator> << '\n';
        std::cout << "proxy_semi_iterator<shade_iterator> is " << xstd::proxy_semi_iterator<shade_iterator> << '\n';
        std::cout << "proxy_iterator<shade*> is " << xstd::proxy_iterator<shade*> << '\n';
}

Output:

plain: light dark
packed: light dark
proxy_iterator<shade_iterator> is true
proxy_semi_iterator<shade_iterator> is true
proxy_iterator<shade*> is false

See also

Entity Relation
proxy_semi_iterator the weaker concept it subsumes
proxy_reference what its reference models