Skip to content

Instantly share code, notes, and snippets.

@rangerz
Last active November 15, 2017 09:53
Show Gist options
  • Save rangerz/f62d52e5120d5d7d1f07 to your computer and use it in GitHub Desktop.
Save rangerz/f62d52e5120d5d7d1f07 to your computer and use it in GitHub Desktop.
[C++] foreach for pure macro, Qt, and boost
/***** macro foreach *****/
#define EASY_FOREACH(it, container) \
for(typeof((container).begin()) it = (container).begin();it != (container).end(); ++it)
/***** qt foreach *****/
template <typename T>
class ForeachContainer {
public:
inline ForeachContainer(const T& t) : c(t), brk(0), i(c.begin()), e(c.end()) { }
const T c; // avoid copy op, using reference (const T &c)
int brk;
typename T::const_iterator i, e;
};
#define QT_FOREACH(variable, container) \
for (ForeachContainer<__typeof__(container)> _container_(container) \
!_container_.brk && _container_.i != _container_.e \
__extension__({ ++_container_.brk; ++_container_.i; }) \
for (variable = *_container_.i;; __extension__({--_container_.brk; break;}))
/***** boost foreach for pair *****/
#include <boost/foreach.hpp>
#include <boost/tuple/tuple.hpp>
namespace __foreach__ {
// NOTE: This is a copied from Boost
// (boost/tuple/detail/tuple_basic_no_partial_spec.hpp) because the
// new 'boost::tuples::ignore' does not work in our 'foreachkey' and
// 'foreachvalue'.
struct swallow_assign {
template<typename T>
swallow_assign const& operator=(const T&) const {
return *this;
}
};
swallow_assign const ignore = swallow_assign();
} /* namespace __foreach__ */
#define BOOST_FOREACH_PAIR(VARFIRST, VARSECOND, COL) \
BOOST_FOREACH_PREAMBLE() \
if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_col) = BOOST_FOREACH_CONTAIN(COL)) {} else \
if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_cur) = BOOST_FOREACH_BEGIN(COL)) {} else \
if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_end) = BOOST_FOREACH_END(COL)) {} else \
for (bool BOOST_FOREACH_ID(_foreach_continue) = true, BOOST_FOREACH_ID(_foreach_onetime) = true; \
BOOST_FOREACH_ID(_foreach_continue) && !BOOST_FOREACH_DONE(COL); \
BOOST_FOREACH_ID(_foreach_continue) ? BOOST_FOREACH_NEXT(COL) : (void)0) \
if (boost::foreach_detail_::set_false(BOOST_FOREACH_ID(_foreach_onetime))) {} else \
for (VARFIRST = BOOST_FOREACH_DEREF(COL).first; \
!BOOST_FOREACH_ID(_foreach_onetime); \
BOOST_FOREACH_ID(_foreach_onetime) = true) \
if (boost::foreach_detail_::set_false(BOOST_FOREACH_ID(_foreach_continue))) {} else \
for (VARSECOND = BOOST_FOREACH_DEREF(COL).second; \
!BOOST_FOREACH_ID(_foreach_continue); \
BOOST_FOREACH_ID(_foreach_continue) = true)
#define FOREACH BOOST_FOREACH
#define FOREACH_PAIR BOOST_FOREACH_PAIR
#define FOREACH_KEY(VAR, COL) \
FOREACH_PAIR (VAR, __foreach__::ignore, COL)
#define FOREACH_VALUE(VAR, COL) \
FOREACH_PAIR (__foreach__::ignore, VAR, COL)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment