/** * \file foreach.h * This file is part of LyX, the document processor. * Licence details can be found in the file COPYING. * * \author Matthias Ettrich * * Full author contact details are available in file CREDITS. * */ #ifndef FOREACH_H #define FOREACH_H // Code stolen from Q_FOREACH, augmented to use a reference to the // original container instead of a copy. Copies are cheap (if not // mutated) for Qt's containers due to copy-on-write. The are less // cheap for Standard containers, that's why the modification. // Drawback is that we can't use temporary containers as they // will be destroyed before the loop is finished. So always write // // Container const & container = functionReturningTemporaryOrReference() // foreach (ContainerItem const & item, container) { // ... // } // // to extend the lifetime of the reference. #if defined(Q_CC_GNU) && !defined(Q_CC_INTEL) /* make use of typeof-extension */ template class ForeachContainer { public: inline ForeachContainer(const T & t) : c(t), brk(0), i(c.begin()), e(c.end()) { } const T & c; int brk; typename T::const_iterator i, e; }; #define 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;})) #else struct ForeachContainerBase {}; template class ForeachContainer : public ForeachContainerBase { public: inline ForeachContainer(const T& t): c(t), brk(0), i(c.begin()), e(c.end()){} const T & c; mutable int brk; mutable typename T::const_iterator i, e; inline bool condition() const { return (!brk++ && i != e); } }; template inline T *foreachPointer(const T &) { return 0; } template inline ForeachContainer foreachContainerNew(const T& t) { return ForeachContainer(t); } template inline const ForeachContainer *foreachContainer(const ForeachContainerBase *base, const T *) { return static_cast *>(base); } #define foreach(variable, container) \ for (const ForeachContainerBase &_container_ = foreachContainerNew(container); \ foreachContainer(&_container_, true ? 0 : foreachPointer(container))->condition(); \ ++foreachContainer(&_container_, true ? 0 : foreachPointer(container))->i) \ for (variable = *foreachContainer(&_container_, true ? 0 : foreachPointer(container))->i; \ foreachContainer(&_container_, true ? 0 : foreachPointer(container))->brk; \ --foreachContainer(&_container_, true ? 0 : foreachPointer(container))->brk) #endif #endif // FOREACH_H