Enable a missing test in the CMake build
[folly.git] / folly / Foreach.h
1 /*
2  * Copyright 2017 Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #pragma once
18
19 /**
20  * This header is deprecated
21  *
22  * Use range-based for loops, and if necessary Ranges-v3.
23  *
24  * Some of the messaging here presumes that you have coded:
25  *
26  *     #include <range/v3/all.hpp>
27  *     using namespace ranges;
28  */
29
30 #include <folly/Preprocessor.h>
31 #include <type_traits>
32
33 /*
34  * Form a local variable name from "FOR_EACH_" x __LINE__, so that
35  * FOR_EACH can be nested without creating shadowed declarations.
36  */
37 #define _FE_ANON(x) FB_CONCATENATE(FOR_EACH_, FB_CONCATENATE(x, __LINE__))
38
39 /*
40  * If you just want the element values, please use:
41  *
42  *    for (auto&& element : collection)
43  *
44  * If you need access to the iterators please write an explicit iterator loop
45  */
46 #define FOR_EACH(i, c)                                  \
47   if (bool _FE_ANON(s1_) = false) {} else               \
48     for (auto && _FE_ANON(s2_) = (c);                   \
49          !_FE_ANON(s1_); _FE_ANON(s1_) = true)          \
50       for (auto i = _FE_ANON(s2_).begin();              \
51            i != _FE_ANON(s2_).end(); ++i)
52
53 /*
54  * If you just want the element values, please use this (ranges-v3) construct:
55  *
56  *    for (auto&& element : collection | view::reverse)
57  *
58  * If you need access to the iterators please write an explicit iterator loop
59  */
60 #define FOR_EACH_R(i, c)                                \
61   if (bool _FE_ANON(s1_) = false) {} else               \
62     for (auto && _FE_ANON(s2_) = (c);                   \
63          !_FE_ANON(s1_); _FE_ANON(s1_) = true)          \
64       for (auto i = _FE_ANON(s2_).rbegin();             \
65            i != _FE_ANON(s2_).rend(); ++i)
66
67 /*
68  * If you just want the element values, please use this (ranges-v3) construct:
69  *
70  *    for (auto&& element : collection | view::zip(view::ints))
71  *
72  * If you need access to the iterators please write an explicit iterator loop
73  * and use a counter variable
74  */
75 #define FOR_EACH_ENUMERATE(count, i, c)                                \
76   if (bool _FE_ANON(s1_) = false) {} else                            \
77     for (auto && FOR_EACH_state2 = (c);                                \
78          !_FE_ANON(s1_); _FE_ANON(s1_) = true)                     \
79       if (size_t _FE_ANON(n1_) = 0) {} else                            \
80         if (const size_t& count = _FE_ANON(n1_)) {} else               \
81           for (auto i = FOR_EACH_state2.begin();                       \
82                i != FOR_EACH_state2.end(); ++_FE_ANON(n1_), ++i)
83 /**
84  * If you just want the keys, please use this (ranges-v3) construct:
85  *
86  *    for (auto&& element : collection | view::keys)
87  *
88  * If you just want the values, please use this (ranges-v3) construct:
89  *
90  *    for (auto&& element : collection | view::values)
91  *
92  * If you need to see both, use:
93  *
94  *    for (auto&& element : collection) {
95  *      auto const& key = element.first;
96  *      auto& value = element.second;
97  *      ......
98  *    }
99  *
100  */
101 #define FOR_EACH_KV(k, v, c)                                  \
102   if (unsigned int _FE_ANON(s1_) = 0) {} else                 \
103     for (auto && _FE_ANON(s2_) = (c);                         \
104          !_FE_ANON(s1_); _FE_ANON(s1_) = 1)                   \
105       for (auto _FE_ANON(s3_) = _FE_ANON(s2_).begin();        \
106            _FE_ANON(s3_) != _FE_ANON(s2_).end();              \
107            _FE_ANON(s1_) == 2                                 \
108              ? ((_FE_ANON(s1_) = 0), ++_FE_ANON(s3_))         \
109              : (_FE_ANON(s3_) = _FE_ANON(s2_).end()))         \
110         for (auto &k = _FE_ANON(s3_)->first;                  \
111              !_FE_ANON(s1_); ++_FE_ANON(s1_))                 \
112           for (auto &v = _FE_ANON(s3_)->second;               \
113                !_FE_ANON(s1_); ++_FE_ANON(s1_))
114
115 namespace folly { namespace detail {
116
117 // Boost 1.48 lacks has_less, we emulate a subset of it here.
118 template <typename T, typename U>
119 class HasLess {
120   struct BiggerThanChar { char unused[2]; };
121   template <typename C, typename D> static char test(decltype(C() < D())*);
122   template <typename, typename> static BiggerThanChar test(...);
123 public:
124   enum { value = sizeof(test<T, U>(0)) == 1 };
125 };
126
127 /**
128  * notThereYet helps the FOR_EACH_RANGE macro by opportunistically
129  * using "<" instead of "!=" whenever available when checking for loop
130  * termination. This makes e.g. examples such as FOR_EACH_RANGE (i,
131  * 10, 5) execute zero iterations instead of looping virtually
132  * forever. At the same time, some iterator types define "!=" but not
133  * "<". The notThereYet function will dispatch differently for those.
134  *
135  * Below is the correct implementation of notThereYet. It is disabled
136  * because of a bug in Boost 1.46: The filesystem::path::iterator
137  * defines operator< (via boost::iterator_facade), but that in turn
138  * uses distance_to which is undefined for that particular
139  * iterator. So HasLess (defined above) identifies
140  * boost::filesystem::path as properly comparable with <, but in fact
141  * attempting to do so will yield a compile-time error.
142  *
143  * The else branch (active) contains a conservative
144  * implementation.
145  */
146
147 #if 0
148
149 template <class T, class U>
150 typename std::enable_if<HasLess<T, U>::value, bool>::type
151 notThereYet(T& iter, const U& end) {
152   return iter < end;
153 }
154
155 template <class T, class U>
156 typename std::enable_if<!HasLess<T, U>::value, bool>::type
157 notThereYet(T& iter, const U& end) {
158   return iter != end;
159 }
160
161 #else
162
163 template <class T, class U>
164 typename std::enable_if<
165   (std::is_arithmetic<T>::value && std::is_arithmetic<U>::value) ||
166   (std::is_pointer<T>::value && std::is_pointer<U>::value),
167   bool>::type
168 notThereYet(T& iter, const U& end) {
169   return iter < end;
170 }
171
172 template <class T, class U>
173 typename std::enable_if<
174   !(
175     (std::is_arithmetic<T>::value && std::is_arithmetic<U>::value) ||
176     (std::is_pointer<T>::value && std::is_pointer<U>::value)
177   ),
178   bool>::type
179 notThereYet(T& iter, const U& end) {
180   return iter != end;
181 }
182
183 #endif
184
185
186 /**
187  * downTo is similar to notThereYet, but in reverse - it helps the
188  * FOR_EACH_RANGE_R macro.
189  */
190 template <class T, class U>
191 typename std::enable_if<HasLess<U, T>::value, bool>::type
192 downTo(T& iter, const U& begin) {
193   return begin < iter--;
194 }
195
196 template <class T, class U>
197 typename std::enable_if<!HasLess<U, T>::value, bool>::type
198 downTo(T& iter, const U& begin) {
199   if (iter == begin) return false;
200   --iter;
201   return true;
202 }
203
204 } }
205
206 /*
207  * Look at the Ranges-v3 views and you'll probably find an easier way to build
208  * the view you want but the equivalent is roughly:
209  *
210  *    for (auto& element : make_iterator_range(begin, end))
211  */
212 #define FOR_EACH_RANGE(i, begin, end)           \
213   for (auto i = (true ? (begin) : (end));       \
214        ::folly::detail::notThereYet(i, (end));  \
215        ++i)
216
217 /*
218  * Look at the Ranges-v3 views and you'll probably find an easier way to build
219  * the view you want but the equivalent is roughly:
220  *
221  *    for (auto& element : make_iterator_range(begin, end) | view::reverse)
222  */
223 #define FOR_EACH_RANGE_R(i, begin, end) \
224   for (auto i = (false ? (begin) : (end)); ::folly::detail::downTo(i, (begin));)