Iterate keys in a C++ map

Viewed 230514

Is there a way to iterate over the keys, not the pairs of a C++ map?

20 Answers

With C++17 you can use a structured binding inside a range-based for loop (adapting John H.'s answer accordingly):

#include <iostream>
#include <map>

int main() {
    std::map<std::string, int> myMap;

    myMap["one"] = 1;
    myMap["two"] = 2;
    myMap["three"] = 3;

    for ( const auto &[key, value]: myMap ) {
        std::cout << key << '\n';
    }
}

Unfortunately the C++17 standard requires you to declare the value variable, even though you're not using it (std::ignore as one would use for std::tie(..) does not work, see this discussion).

Some compilers may therefore warn you about the unused value variable! Compile-time warnings regarding unused variables are a no-go for any production code in my mind. So, this may not be applicable for certain compiler versions.

Without BOOST, directly using key and value

for(auto const& [key, value]: m_map)
    {
    std::cout<<" key="<<key;
    std::cout<<" value="<<value<<std::endl;
    }

With C++20, we have access to the ranges library, which has a nifty solution for this: std::views::keys

#include <ranges>

//...

std::map<int, int> myMap = {{1,2},{3,4},{5,6}};
auto keys = std::views::keys(myMap);
for(auto key : keys) {
    std::cout << key << std::endl;
}

Try it out yourself: https://godbolt.org/z/heeWv4Gh6

I've adopted Ian's answer to work with all map types and fixed returning a reference for operator*

template<typename T>
class MapKeyIterator : public T
{
public:
    MapKeyIterator() : T() {}
    MapKeyIterator(T iter) : T(iter) {}
    auto* operator->()
    {
        return &(T::operator->()->first);
    }
    auto& operator*()
    {
        return T::operator*().first;
    }
};
Related