Apache Mesos
foreach.hpp
Go to the documentation of this file.
1 // Licensed under the Apache License, Version 2.0 (the "License");
2 // you may not use this file except in compliance with the License.
3 // You may obtain a copy of the License at
4 //
5 // http://www.apache.org/licenses/LICENSE-2.0
6 //
7 // Unless required by applicable law or agreed to in writing, software
8 // distributed under the License is distributed on an "AS IS" BASIS,
9 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 // See the License for the specific language governing permissions and
11 // limitations under the License.
12 
13 #ifndef __STOUT_FOREACH_HPP__
14 #define __STOUT_FOREACH_HPP__
15 
16 #include <tuple>
17 #include <utility>
18 
19 #include <stout/preprocessor.hpp>
20 
21 #define STOUT_FOREACH_PREFIX CAT(__foreach_, __LINE__)
22 #define STOUT_FOREACH_BODY CAT(STOUT_FOREACH_PREFIX, _body__)
23 #define STOUT_FOREACH_BREAK CAT(STOUT_FOREACH_PREFIX, _break__)
24 #define STOUT_FOREACH_CONTINUE CAT(STOUT_FOREACH_PREFIX, _continue__)
25 #define STOUT_FOREACH_ELEM CAT(STOUT_FOREACH_PREFIX, _elem__)
26 #define STOUT_FOREACH_ONCE CAT(STOUT_FOREACH_PREFIX, _once__)
27 
28 
29 // `foreach` is a trivial expansion to the range-based `for`.
30 #define foreach(ELEM, ELEMS) for (ELEM : ELEMS)
31 
32 
33 // `foreachpair` is used to unpack the key and value of the pairs coming out of
34 // a sequence. e.g., std::map.
35 //
36 // Control flow:
37 //
38 // Labels:
39 // * `STOUT_FOREACH_BREAK` is the label that when jumped to, breaks out of
40 // the loop.
41 // * `STOUT_FOREACH_BODY` is the label that helps to skip the loop exit checks
42 // (break or continue) until we finish the current iteration.
43 //
44 // Flags:
45 // * `STOUT_FOREACH_CONTINUE` determines whether the loop should continue or
46 // not. If we encounter a `break`, this will be `false`. If we encounter a
47 // `continue` or run the current iteration to completion,
48 // `STOUT_FOREACH_CONTINUE` will be set to `true`.
49 // * `STOUT_FOREACH_ONCE` is used to execute a `for` loop exactly once.
50 //
51 #define foreachpair(KEY, VALUE, ELEMS) \
52  foreach (auto&& STOUT_FOREACH_ELEM, ELEMS) \
53  if (false) STOUT_FOREACH_BREAK: break; /* set up the break path */ \
54  else if (bool STOUT_FOREACH_CONTINUE = false) {} /* var decl */ \
55  else if (true) goto STOUT_FOREACH_BODY; /* skip the loop exit checks */ \
56  else for (;;) /* determine whether we should break or continue. */ \
57  if (!STOUT_FOREACH_CONTINUE) goto STOUT_FOREACH_BREAK; /* break */ \
58  else if (true) break; /* continue */ \
59  else \
60  STOUT_FOREACH_BODY: \
61  if (bool STOUT_FOREACH_ONCE = false) {} /* var decl */ \
62  else for (KEY = std::get<0>( \
63  std::forward<decltype(STOUT_FOREACH_ELEM)>( \
64  STOUT_FOREACH_ELEM)); \
65  !STOUT_FOREACH_ONCE; \
66  STOUT_FOREACH_ONCE = true) \
67  for (VALUE = std::get<1>( \
68  std::forward<decltype(STOUT_FOREACH_ELEM)>( \
69  STOUT_FOREACH_ELEM)); \
70  !STOUT_FOREACH_CONTINUE; \
71  STOUT_FOREACH_CONTINUE = true)
72 
73 
74 #define foreachkey(KEY, ELEMS) foreachpair (KEY, std::ignore, ELEMS)
75 
76 
77 #define foreachvalue(VALUE, ELEMS) foreachpair (std::ignore, VALUE, ELEMS)
78 
79 #endif // __STOUT_FOREACH_HPP__