#include <tuple>
#include <utility>

#include <boost/preprocessor.hpp>

#define FOREACH_PREFIX BOOST_PP_CAT(__foreach_, __LINE__)

#define FOREACH_BODY     BOOST_PP_CAT(FOREACH_PREFIX, _body__)
#define FOREACH_BREAK    BOOST_PP_CAT(FOREACH_PREFIX, _break__)
#define FOREACH_CONTINUE BOOST_PP_CAT(FOREACH_PREFIX, _continue__)
#define FOREACH_ELEM     BOOST_PP_CAT(FOREACH_PREFIX, _elem__)
#define FOREACH_ONCE     BOOST_PP_CAT(FOREACH_PREFIX, _once__)

#define foreachpair(KEY, VALUE, ELEMS)                                     \
  for (auto&& FOREACH_ELEM : ELEMS)                                        \
    if (false) FOREACH_BREAK: break; /* set up the break path */           \
    else if (bool FOREACH_CONTINUE = false) {} /* var decl */              \
    else if (true) goto FOREACH_BODY; /* skip the loop exit checks */      \
    else for (;;) /* determine whether we should break or continue. */     \
      if (!FOREACH_CONTINUE) goto FOREACH_BREAK; /* break */               \
      else if (true) break; /* continue */                                 \
      else                                                                 \
        FOREACH_BODY:                                                      \
        if (bool FOREACH_ONCE = false) {} /* var decl */                   \
        else for (KEY = std::get<0>(                                       \
                      std::forward<decltype(FOREACH_ELEM)>(FOREACH_ELEM)); \
                  !FOREACH_ONCE;                                           \
                  FOREACH_ONCE = true)                                     \
          for (VALUE = std::get<1>(                                        \
                   std::forward<decltype(FOREACH_ELEM)>(FOREACH_ELEM));    \
               !FOREACH_CONTINUE;                                          \
               FOREACH_CONTINUE = true)

/* -------------------------------------------------------------------------- */

#include <iostream>
#include <map>
#include <vector>

int main() {
  {
  	std::cout << "{}: start" << std::endl;
    std::map<int, double> elems;
    foreachpair (int key, double value, elems) {
      std::cout << key << " " << value << std::endl;
    }
    std::cout << "{}: end" << std::endl;
  }
  {
  	std::cout << "{{101, 202}, {303, 404}}: start" << std::endl;
    std::map<int, int> elems = {{101, 202}, {303, 404}};
    foreachpair (int key, int value, elems) {
      std::cout << key << " " << value << std::endl;
    }
    std::cout << "{{101, 202}, {303, 404}}: end" << std::endl;
  }
  {
  	std::cout << "break: {{1, 2}, {3, 4}}: start" << std::endl;
    std::map<int, int> elems = {{1, 2}, {3, 4}};
    foreachpair (int key, int value, elems) {
      std::cout << key << " " << value << std::endl;
      if (key == 1) break;
    }
    std::cout << "break: {{1, 2}, {3, 4}}: end" << std::endl;
  }
  {
  	std::cout << "continue: {{1, 2}, {3, 4}}: start" << std::endl;
    std::map<int, int> elems = {{1, 2}, {3, 4}};
    foreachpair (int key, int value, elems) {
      if (key == 1) continue;
      std::cout << key << " " << value << std::endl;
    }
    std::cout << "continue: {{1, 2}, {3, 4}}: end" << std::endl;
  }
  {
  	std::cout << "{{1, 2}, {3, 4}}: start" << std::endl;
    std::vector<std::tuple<int, int>> elems = {std::make_tuple(1, 2),
                                               std::make_tuple(3, 4)};
    foreachpair (int key, int value, elems) {
      std::cout << key << " " << value << std::endl;
    }
    std::cout << "{{1, 2}, {3, 4}}: end" << std::endl;
  }
}