Remove template helper constants
[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
124  public:
125   enum { value = sizeof(test<T, U>(0)) == 1 };
126 };
127
128 /**
129  * notThereYet helps the FOR_EACH_RANGE macro by opportunistically
130  * using "<" instead of "!=" whenever available when checking for loop
131  * termination. This makes e.g. examples such as FOR_EACH_RANGE (i,
132  * 10, 5) execute zero iterations instead of looping virtually
133  * forever. At the same time, some iterator types define "!=" but not
134  * "<". The notThereYet function will dispatch differently for those.
135  *
136  * Below is the correct implementation of notThereYet. It is disabled
137  * because of a bug in Boost 1.46: The filesystem::path::iterator
138  * defines operator< (via boost::iterator_facade), but that in turn
139  * uses distance_to which is undefined for that particular
140  * iterator. So HasLess (defined above) identifies
141  * boost::filesystem::path as properly comparable with <, but in fact
142  * attempting to do so will yield a compile-time error.
143  *
144  * The else branch (active) contains a conservative
145  * implementation.
146  */
147
148 #if 0
149
150 template <class T, class U>
151 typename std::enable_if<HasLess<T, U>::value, bool>::type
152 notThereYet(T& iter, const U& end) {
153   return iter < end;
154 }
155
156 template <class T, class U>
157 typename std::enable_if<!HasLess<T, U>::value, bool>::type
158 notThereYet(T& iter, const U& end) {
159   return iter != end;
160 }
161
162 #else
163
164 template <class T, class U>
165 typename std::enable_if<
166   (std::is_arithmetic<T>::value && std::is_arithmetic<U>::value) ||
167   (std::is_pointer<T>::value && std::is_pointer<U>::value),
168   bool>::type
169 notThereYet(T& iter, const U& end) {
170   return iter < end;
171 }
172
173 template <class T, class U>
174 typename std::enable_if<
175   !(
176     (std::is_arithmetic<T>::value && std::is_arithmetic<U>::value) ||
177     (std::is_pointer<T>::value && std::is_pointer<U>::value)
178   ),
179   bool>::type
180 notThereYet(T& iter, const U& end) {
181   return iter != end;
182 }
183
184 #endif
185
186
187 /**
188  * downTo is similar to notThereYet, but in reverse - it helps the
189  * FOR_EACH_RANGE_R macro.
190  */
191 template <class T, class U>
192 typename std::enable_if<HasLess<U, T>::value, bool>::type
193 downTo(T& iter, const U& begin) {
194   return begin < iter--;
195 }
196
197 template <class T, class U>
198 typename std::enable_if<!HasLess<U, T>::value, bool>::type
199 downTo(T& iter, const U& begin) {
200   if (iter == begin) return false;
201   --iter;
202   return true;
203 }
204
205 } }
206
207 /*
208  * Look at the Ranges-v3 views and you'll probably find an easier way to build
209  * the view you want but the equivalent is roughly:
210  *
211  *    for (auto& element : make_iterator_range(begin, end))
212  */
213 #define FOR_EACH_RANGE(i, begin, end)           \
214   for (auto i = (true ? (begin) : (end));       \
215        ::folly::detail::notThereYet(i, (end));  \
216        ++i)
217
218 /*
219  * Look at the Ranges-v3 views and you'll probably find an easier way to build
220  * the view you want but the equivalent is roughly:
221  *
222  *    for (auto& element : make_iterator_range(begin, end) | view::reverse)
223  */
224 #define FOR_EACH_RANGE_R(i, begin, end) \
225   for (auto i = (false ? (begin) : (end)); ::folly::detail::downTo(i, (begin));)