Foreach.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. /*
  2. * Copyright 2011-present 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. #pragma once
  17. #include <folly/Portability.h>
  18. #include <folly/Preprocessor.h>
  19. #include <type_traits>
  20. namespace folly {
  21. /**
  22. * @function for_each
  23. *
  24. * folly::for_each is a generalized iteration algorithm. Example:
  25. *
  26. * auto one = std::make_tuple(1, 2, 3);
  27. * auto two = std::vector<int>{1, 2, 3};
  28. * auto func = [](auto element, auto index) {
  29. * cout << index << " : " << element << endl;
  30. * };
  31. * folly::for_each(one, func);
  32. * folly::for_each(two, func);
  33. *
  34. * The for_each function allows iteration through sequences, these can either be
  35. * runtime sequences (i.e. entities for which std::begin and std::end work) or
  36. * compile time sequences (as deemed by the presence of std::tuple_length<> and
  37. * member get<> or ADL get<> functions).
  38. *
  39. * If a sequence type is both a runtime sequence (aka range) and a compile-time
  40. * sequence (aka tuple), then it is treated as a range in preference to a tuple.
  41. * An example of such a type is std::array.
  42. *
  43. * The function is made to provide a convenient library based alternative to the
  44. * proposal p0589r0, which aims to generalize the range based for loop even
  45. * further to work with compile time sequences.
  46. *
  47. * A drawback of using range based for loops is that sometimes you do not have
  48. * access to the index within the range. This provides easy access to that, even
  49. * with compile time sequences.
  50. *
  51. * And breaking out is easy:
  52. *
  53. * auto range_one = std::vector<int>{1, 2, 3};
  54. * auto range_two = std::make_tuple(1, 2, 3);
  55. * auto func = [](auto ele, auto index) {
  56. * cout << "Element at index " << index << " : " << ele;
  57. * if (index == 1) {
  58. * return folly::loop_break;
  59. * }
  60. * return folly::loop_continue;
  61. * };
  62. * folly_for_each(range_one, func);
  63. * folly_for_each(range_two, func);
  64. *
  65. * A simple use case would be when using futures, if the user was doing calls to
  66. * n servers then they would accept the callback with the futures like this:
  67. *
  68. * auto vec = std::vector<std::future<int>>{request_one(), ...};
  69. * when_all(vec.begin(), vec.end()).then([](auto futures) {
  70. * folly::for_each(futures, [](auto& fut) { ... });
  71. * });
  72. *
  73. * Now when this code switches to use tuples instead of the runtime std::vector,
  74. * then the loop does not need to change, the code will still work just fine:
  75. *
  76. * when_all(future_one, future_two, future_three).then([](auto futures) {
  77. * folly::for_each(futures, [](auto& fut) { ... });
  78. * });
  79. */
  80. template <typename Range, typename Func>
  81. FOLLY_CPP14_CONSTEXPR Func for_each(Range&& range, Func func);
  82. /**
  83. * The user should return loop_break and loop_continue if they want to iterate
  84. * in such a way that they can preemptively stop the loop and break out when
  85. * certain conditions are met.
  86. */
  87. namespace for_each_detail {
  88. enum class LoopControl : bool { BREAK, CONTINUE };
  89. } // namespace for_each_detail
  90. constexpr auto loop_break = for_each_detail::LoopControl::BREAK;
  91. constexpr auto loop_continue = for_each_detail::LoopControl::CONTINUE;
  92. /**
  93. * Utility method to help access elements of a sequence with one uniform
  94. * interface.
  95. *
  96. * This can be useful for example when you are looping through a sequence and
  97. * want to modify another sequence based on the information in the current
  98. * sequence:
  99. *
  100. * auto range_one = std::make_tuple(1, 2, 3);
  101. * auto range_two = std::make_tuple(4, 5, 6);
  102. * folly::for_each(range_one, [&range_two](auto ele, auto index) {
  103. * folly::fetch(range_two, index) = ele;
  104. * });
  105. *
  106. * For ranges, this works by first trying to use the iterator class if the
  107. * iterator has been marked to be a random access iterator. This should be
  108. * inspectable via the std::iterator_traits traits class. If the iterator class
  109. * is not present or is not a random access iterator then the implementation
  110. * falls back to trying to use the indexing operator (operator[]) to fetch the
  111. * required element.
  112. */
  113. template <typename Sequence, typename Index>
  114. FOLLY_CPP14_CONSTEXPR decltype(auto) fetch(Sequence&& sequence, Index&& index);
  115. } // namespace folly
  116. /**
  117. * Everything below is deprecated.
  118. */
  119. /*
  120. * Form a local variable name from "FOR_EACH_" x __LINE__, so that
  121. * FOR_EACH can be nested without creating shadowed declarations.
  122. */
  123. #define _FE_ANON(x) FB_CONCATENATE(FOR_EACH_, FB_CONCATENATE(x, __LINE__))
  124. /*
  125. * If you just want the element values, please use:
  126. *
  127. * for (auto&& element : collection)
  128. *
  129. * If you need access to the iterators please write an explicit iterator loop
  130. */
  131. #define FOR_EACH(i, c) \
  132. if (bool _FE_ANON(s1_) = false) { \
  133. } else \
  134. for (auto&& _FE_ANON(s2_) = (c); !_FE_ANON(s1_); _FE_ANON(s1_) = true) \
  135. for (auto i = _FE_ANON(s2_).begin(); i != _FE_ANON(s2_).end(); ++i)
  136. /*
  137. * If you just want the element values, please use this (ranges-v3) construct:
  138. *
  139. * for (auto&& element : collection | view::reverse)
  140. *
  141. * If you need access to the iterators please write an explicit iterator loop
  142. */
  143. #define FOR_EACH_R(i, c) \
  144. if (bool _FE_ANON(s1_) = false) { \
  145. } else \
  146. for (auto&& _FE_ANON(s2_) = (c); !_FE_ANON(s1_); _FE_ANON(s1_) = true) \
  147. for (auto i = _FE_ANON(s2_).rbegin(); i != _FE_ANON(s2_).rend(); ++i)
  148. /*
  149. * If you just want the element values, please use this construct:
  150. *
  151. * for (auto&& element : folly::enumerate(collection))
  152. *
  153. * If you need access to the iterators please write an explicit iterator loop
  154. * and use a counter variable
  155. */
  156. #define FOR_EACH_ENUMERATE(count, i, c) \
  157. if (bool _FE_ANON(s1_) = false) { \
  158. } else \
  159. for (auto&& FOR_EACH_state2 = (c); !_FE_ANON(s1_); _FE_ANON(s1_) = true) \
  160. if (size_t _FE_ANON(n1_) = 0) { \
  161. } else if (const size_t& count = _FE_ANON(n1_)) { \
  162. } else \
  163. for (auto i = FOR_EACH_state2.begin(); i != FOR_EACH_state2.end(); \
  164. ++_FE_ANON(n1_), ++i)
  165. /**
  166. * If you just want the keys, please use this (ranges-v3) construct:
  167. *
  168. * for (auto&& element : collection | view::keys)
  169. *
  170. * If you just want the values, please use this (ranges-v3) construct:
  171. *
  172. * for (auto&& element : collection | view::values)
  173. *
  174. * If you need to see both, use:
  175. *
  176. * for (auto&& element : collection) {
  177. * auto const& key = element.first;
  178. * auto& value = element.second;
  179. * ......
  180. * }
  181. *
  182. */
  183. #define FOR_EACH_KV(k, v, c) \
  184. if (unsigned int _FE_ANON(s1_) = 0) { \
  185. } else \
  186. for (auto&& _FE_ANON(s2_) = (c); !_FE_ANON(s1_); _FE_ANON(s1_) = 1) \
  187. for (auto _FE_ANON(s3_) = _FE_ANON(s2_).begin(); \
  188. _FE_ANON(s3_) != _FE_ANON(s2_).end(); \
  189. _FE_ANON(s1_) == 2 ? ((_FE_ANON(s1_) = 0), ++_FE_ANON(s3_)) \
  190. : (_FE_ANON(s3_) = _FE_ANON(s2_).end())) \
  191. for (auto& k = _FE_ANON(s3_)->first; !_FE_ANON(s1_); ++_FE_ANON(s1_)) \
  192. for (auto& v = _FE_ANON(s3_)->second; !_FE_ANON(s1_); ++_FE_ANON(s1_))
  193. namespace folly {
  194. namespace detail {
  195. // Boost 1.48 lacks has_less, we emulate a subset of it here.
  196. template <typename T, typename U>
  197. class HasLess {
  198. struct BiggerThanChar {
  199. char unused[2];
  200. };
  201. template <typename C, typename D>
  202. static char test(decltype(C() < D())*);
  203. template <typename, typename>
  204. static BiggerThanChar test(...);
  205. public:
  206. enum { value = sizeof(test<T, U>(nullptr)) == 1 };
  207. };
  208. /**
  209. * notThereYet helps the FOR_EACH_RANGE macro by opportunistically
  210. * using "<" instead of "!=" whenever available when checking for loop
  211. * termination. This makes e.g. examples such as FOR_EACH_RANGE (i,
  212. * 10, 5) execute zero iterations instead of looping virtually
  213. * forever. At the same time, some iterator types define "!=" but not
  214. * "<". The notThereYet function will dispatch differently for those.
  215. *
  216. * Below is the correct implementation of notThereYet. It is disabled
  217. * because of a bug in Boost 1.46: The filesystem::path::iterator
  218. * defines operator< (via boost::iterator_facade), but that in turn
  219. * uses distance_to which is undefined for that particular
  220. * iterator. So HasLess (defined above) identifies
  221. * boost::filesystem::path as properly comparable with <, but in fact
  222. * attempting to do so will yield a compile-time error.
  223. *
  224. * The else branch (active) contains a conservative
  225. * implementation.
  226. */
  227. #if 0
  228. template <class T, class U>
  229. typename std::enable_if<HasLess<T, U>::value, bool>::type
  230. notThereYet(T& iter, const U& end) {
  231. return iter < end;
  232. }
  233. template <class T, class U>
  234. typename std::enable_if<!HasLess<T, U>::value, bool>::type
  235. notThereYet(T& iter, const U& end) {
  236. return iter != end;
  237. }
  238. #else
  239. template <class T, class U>
  240. typename std::enable_if<
  241. (std::is_arithmetic<T>::value && std::is_arithmetic<U>::value) ||
  242. (std::is_pointer<T>::value && std::is_pointer<U>::value),
  243. bool>::type
  244. notThereYet(T& iter, const U& end) {
  245. return iter < end;
  246. }
  247. template <class T, class U>
  248. typename std::enable_if<
  249. !((std::is_arithmetic<T>::value && std::is_arithmetic<U>::value) ||
  250. (std::is_pointer<T>::value && std::is_pointer<U>::value)),
  251. bool>::type
  252. notThereYet(T& iter, const U& end) {
  253. return iter != end;
  254. }
  255. #endif
  256. /**
  257. * downTo is similar to notThereYet, but in reverse - it helps the
  258. * FOR_EACH_RANGE_R macro.
  259. */
  260. template <class T, class U>
  261. typename std::enable_if<HasLess<U, T>::value, bool>::type downTo(
  262. T& iter,
  263. const U& begin) {
  264. return begin < iter--;
  265. }
  266. template <class T, class U>
  267. typename std::enable_if<!HasLess<U, T>::value, bool>::type downTo(
  268. T& iter,
  269. const U& begin) {
  270. if (iter == begin) {
  271. return false;
  272. }
  273. --iter;
  274. return true;
  275. }
  276. } // namespace detail
  277. } // namespace folly
  278. /*
  279. * Look at the Ranges-v3 views and you'll probably find an easier way to build
  280. * the view you want but the equivalent is roughly:
  281. *
  282. * for (auto& element : make_iterator_range(begin, end))
  283. */
  284. #define FOR_EACH_RANGE(i, begin, end) \
  285. for (auto i = (true ? (begin) : (end)); \
  286. ::folly::detail::notThereYet(i, (end)); \
  287. ++i)
  288. /*
  289. * Look at the Ranges-v3 views and you'll probably find an easier way to build
  290. * the view you want but the equivalent is roughly:
  291. *
  292. * for (auto& element : make_iterator_range(begin, end) | view::reverse)
  293. */
  294. #define FOR_EACH_RANGE_R(i, begin, end) \
  295. for (auto i = (false ? (begin) : (end)); ::folly::detail::downTo(i, (begin));)
  296. #include <folly/container/Foreach-inl.h>