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