Qt foreach-like alternative to iterate over value AND key of an associative container The Qt documentation recommend an iterator-based solution to iterate over an associative container like QMap and QHash, and I always wondered if there really isn't a (nice) solution using a foreach loop like in PHP:



foreach($container as $key =&gt; $value)


I looked into the source code of the foreach macro and extended it by a key variable. The following code is only the GCC version of the loop (it doesn't work with all compilers, see Q_FOREACH macro definition in qglobal.h for other versions).



#define foreachkv(keyvar, variable, container)                        \
for (QForeachContainer&lt;__typeof__(container)&gt; _container_(container); \
     !_container_.brk &amp;&amp; _container_.i != _container_.e;              \
     __extension__  ({ ++_container_.brk; ++_container_.i; }))        \
    for (keyvar = _container_.i.key();; __extension__ ({break;}))     \
        for (variable = *_container_.i;; __extension__ ({--_container_.brk; break;}))


Now you can do the following:

QVariantHash m;
m.insert("test", 42);
m.insert("foo", true);
foreachkv(QString k, QVariant v, m)
    qDebug() &lt;&lt; k &lt;&lt; "=&gt;" &lt;&lt; v;


The output will be:


"foo" =&gt; QVariant(bool, true) 
"test" =&gt; QVariant(int, 42)



Tests I've done so far:


examples from above
foreachkv works as expected with break and continue statements within the loop.


What did I do? I just added another for loop to introduce the key variable (called keyvar in the macro). Maybe I don't need this loop?
You can probably do something simpler to avoid making this a special case macro, e.g. using std::tie or boost::tie if that's not available:

#include &lt;map&gt;
#include &lt;functional&gt;
#include &lt;boost/foreach.hpp&gt;
#include &lt;iostream&gt;

int main() {
  std::map&lt;int, std::string&gt; map = {std::make_pair(1,"one"), std::make_pair(2,"two")};
  int k;
  std::string v;
  BOOST_FOREACH(std::tie(k, v), map) {
    std::cout &lt;&lt; "k=" &lt;&lt; k &lt;&lt; " - " &lt;&lt; v &lt;&lt; std::endl;
  }
}