Quick Q:Is it possible in C++ to iterate over a std::map with unpacked key and value?

Quick A: An easy solution is not supported by the standard, it may come later.

Recently on SO:

Is it possible in C++ to do std::map<> “for element : container” iteration with named variables (eg, key and value) instead of .first and .second?

You could write a class template:

template <class K, class T>
struct MapElem {
    K const& key;
    T& value;

    MapElem(std::pair<K const, T>& pair)
        : key(pair.first)
        , value(pair.second)
    { }
};

with the advantage of being able to write key and value but with the disadvantage of having to specify the types:

for ( MapElem<int, std::string> kv : my_map ){
    std::cout << kv.key << " --> " << kv.value;
}

And that won't work if my_map were const either. You'd have to do something like:

template <class K, class T>
struct MapElem {
    K const& key;
    T& value;

    MapElem(std::pair<K const, T>& pair)
        : key(pair.first)
        , value(pair.second)
    { }

    MapElem(const std::pair<K const, std::remove_const_t<T>>& pair)
        : key(pair.first)
        , value(pair.second)
    { }
};

for ( MapElem<int, const std::string> kv : my_map ){
    std::cout << kv.key << " --> " << kv.value;
}

It's a mess. Best thing for now is to just get used to writing .first and .second and hope that the structured bindings proposal passes, which would allow for what you really want:

for (auto&& [key, value] : my_map) {
    std::cout << key << " --> " << value;
}

Add a Comment

Comments are closed.

Comments (1)

0 0

guido said on Apr 12, 2016 04:32 AM:

To avoid specifying types this should do

template <class K, class T>
auto type(const std::map<K, T>& map ) -> const MapElemConst<K, T> { }

std::map<int, std::string> my_map;
for ( decltype ( type(my_map) ) kv : my_map ){
std::cout << kv.key << " --> " << kv.value << std::endl;
}