C++20 std::map iterators with key or value access

Sometimes you want to iterate only the keys or values of a std::map or std::unordered_map. The AccessIterator allows just that, avoiding use of the less-than-transparent std::pair<>. It also handles const and non-const containers automatically.

Iterator code


    /*
        Copyright Niels Moseley, 2024

        SPDX-License-Identifier: LSC
    */

    #pragma once
    #include <iterator>

    namespace MapIterators
    {

    /** Iterator for std::map and std::unordered_map, both const and non-const
        with Accessor callable that returns an item form the container
    */
    template<typename Accessor, typename Container>
    struct AccessIterator
    {
        using ContainerType = typename std::remove_reference_t<Container>;

        AccessIterator(Container &container) : m_container(container) {}

        auto begin()
        {
            return IteratorWrapper(m_container.begin());
        }

        auto end()
        {
            return IteratorWrapper(m_container.end());
        }

        ContainerType &m_container;

        template<typename It>
        struct IteratorWrapper
        {
            IteratorWrapper(It iter) : m_iter(iter) {}

            constexpr auto operator++()
            {
                return ++m_iter;
            }

            constexpr auto operator++(int)
            {
                return m_iter++;
            }

            auto& operator*()
            {
                return m_accessor(*m_iter);
            }

            constexpr bool operator==(const IteratorWrapper &other) noexcept
            {
                return m_iter == other.m_iter;
            }

            constexpr bool operator!=(const IteratorWrapper &other) noexcept
            {
                return m_iter != other.m_iter;
            }

            Accessor m_accessor;
            It m_iter;
        };
    };


    struct KeyAccessor
    {
        auto& operator()(auto &v)
        {
            return v.first;
        }
    };

    struct ValueAccessor
    {
        auto& operator()(auto &v)
        {
            return v.second;
        }
    };

    constexpr auto keys(auto &MapContainer)
    {
        return MapIterators::AccessIterator<KeyAccessor, decltype(MapContainer)>(MapContainer);
    }

    constexpr auto values(auto &MapContainer)
    {
        return MapIterators::AccessIterator<ValueAccessor, decltype(MapContainer)>(MapContainer);
    }
};

Usage


    std::map<std::size_t, std::string> myMap;

    myMap[0]  = "Testing123";
    myMap[1]  = "Hello, world!";
    myMap[99] = "Luftballons";

    for(auto key : MapIterators::keys(myMap))
    {
        std::cout << "key: " << key << "\n";
    }

    for(auto &value : MapIterators::values(myMap))
    {
        std::cout << "value: " << value << "\n";
    }