]> git.lyx.org Git - lyx.git/blob - src/support/foreach.h
there is no trunk/src/intl folder
[lyx.git] / src / support / foreach.h
1
2 /**
3  * \file foreach.h
4  * This file is part of LyX, the document processor.
5  * Licence details can be found in the file COPYING.
6  *
7  * \author Matthias Ettrich
8  *
9  * Full author contact details are available in file CREDITS.
10  *
11  */
12
13 #ifndef FOREACH_H
14 #define FOREACH_H
15
16 // Code stolen from Q_FOREACH, augmented to use a reference to the
17 // original container instead of a copy. Copies are cheap (if not
18 // mutated) for Qt's containers due to copy-on-write. The are less
19 // cheap for Standard containers, that's why the modification.
20 // Drawback is that we can't use temporary containers as they
21 // will be destroyed before the loop is finished. So always write
22 //  
23 //  Container const & container = functionReturningTemporaryOrReference()
24 //  foreach (ContainerItem const & item, container) {
25 //   ...
26 //  }
27 //
28 // to extend the lifetime of the reference.
29
30 #if defined(Q_CC_GNU) && !defined(Q_CC_INTEL)
31
32 /* make use of typeof-extension */
33 template <typename T>
34 class ForeachContainer {
35 public:
36     inline ForeachContainer(const T & t) : c(t), brk(0), i(c.begin()), e(c.end()) { }
37     const T & c;
38     int brk;
39     typename T::const_iterator i, e;
40 };
41
42 #define foreach(variable, container)                                  \
43 for (ForeachContainer<__typeof__(container)> _container_(container);  \
44      !_container_.brk && _container_.i != _container_.e;              \
45      __extension__  ({ ++_container_.brk; ++_container_.i; }))        \
46     for (variable = *_container_.i;; __extension__ ({--_container_.brk; break;}))
47
48 #else 
49
50 struct ForeachContainerBase {};
51
52 template <typename T>
53 class ForeachContainer : public ForeachContainerBase {
54 public:
55     inline ForeachContainer(const T& t): c(t), brk(0), i(c.begin()), e(c.end()){};
56     const T & c;
57     mutable int brk;
58     mutable typename T::const_iterator i, e;
59     inline bool condition() const { return (!brk++ && i != e); }
60 };
61
62 template <typename T> inline T *foreachPointer(const T &) { return 0; }
63
64 template <typename T> inline ForeachContainer<T> foreachContainerNew(const T& t)
65 { return ForeachContainer<T>(t); }
66
67 template <typename T>
68 inline const ForeachContainer<T> *foreachContainer(const ForeachContainerBase *base, const T *)
69 { return static_cast<const ForeachContainer<T> *>(base); }
70
71 #define foreach(variable, container) \
72         for (const ForeachContainerBase &_container_ = foreachContainerNew(container); \
73                          foreachContainer(&_container_, true ? 0 : foreachPointer(container))->condition();       \
74                          ++foreachContainer(&_container_, true ? 0 : foreachPointer(container))->i)               \
75                         for (variable = *foreachContainer(&_container_, true ? 0 : foreachPointer(container))->i; \
76                                          foreachContainer(&_container_, true ? 0 : foreachPointer(container))->brk;           \
77                                          --foreachContainer(&_container_, true ? 0 : foreachPointer(container))->brk)
78 #endif
79
80 #endif // FOREACH_H