Foreach-inl.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. /*
  2. * Copyright 2017-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. #include <cassert>
  17. #include <cstdint>
  18. #include <initializer_list>
  19. #include <iterator>
  20. #include <tuple>
  21. #include <type_traits>
  22. #include <utility>
  23. #include <folly/Portability.h>
  24. #include <folly/Traits.h>
  25. #include <folly/Utility.h>
  26. #include <folly/functional/Invoke.h>
  27. namespace folly {
  28. namespace for_each_detail {
  29. namespace adl {
  30. /* using override */
  31. using std::begin;
  32. /* using override */
  33. using std::end;
  34. /* using override */
  35. using std::get;
  36. /**
  37. * The adl_ functions below lookup the function name in the namespace of the
  38. * type of the object being passed into the function. If no function with that
  39. * name exists for the passed object then the default std:: versions are going
  40. * to be called
  41. */
  42. template <std::size_t Index, typename Type>
  43. auto adl_get(Type&& instance) -> decltype(get<Index>(std::declval<Type>())) {
  44. return get<Index>(std::forward<Type>(instance));
  45. }
  46. template <typename Type>
  47. auto adl_begin(Type&& instance) -> decltype(begin(instance)) {
  48. return begin(instance);
  49. }
  50. template <typename Type>
  51. auto adl_end(Type&& instance) -> decltype(end(instance)) {
  52. return end(instance);
  53. }
  54. } // namespace adl
  55. /**
  56. * Enable if the tuple supports fetching via a member get<>()
  57. */
  58. template <typename T>
  59. using EnableIfMemberGetFound =
  60. void_t<decltype(std::declval<T>().template get<0>())>;
  61. template <typename, typename T>
  62. struct IsMemberGetFound : std::false_type {};
  63. template <typename T>
  64. struct IsMemberGetFound<EnableIfMemberGetFound<T>, T> : std::true_type {};
  65. /**
  66. * A get that tries member get<> first and if that is not found tries ADL get<>.
  67. * This mechanism is as found in the structured bindings proposal here 11.5.3.
  68. * http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4659.pdf
  69. */
  70. template <
  71. std::size_t Index,
  72. typename Type,
  73. std::enable_if_t<!IsMemberGetFound<void, Type>::value, int> = 0>
  74. auto get_impl(Type&& instance)
  75. -> decltype(adl::adl_get<Index>(static_cast<Type&&>(instance))) {
  76. return adl::adl_get<Index>(static_cast<Type&&>(instance));
  77. }
  78. template <
  79. std::size_t Index,
  80. typename Type,
  81. std::enable_if_t<IsMemberGetFound<void, Type>::value, int> = 0>
  82. auto get_impl(Type&& instance)
  83. -> decltype(static_cast<Type&&>(instance).template get<Index>()) {
  84. return static_cast<Type&&>(instance).template get<Index>();
  85. }
  86. /**
  87. * Check if the sequence is a tuple
  88. */
  89. template <typename Type, typename T = typename std::decay<Type>::type>
  90. using EnableIfTuple = void_t<
  91. decltype(get_impl<0>(std::declval<T>())),
  92. decltype(std::tuple_size<T>::value)>;
  93. template <typename, typename T>
  94. struct IsTuple : std::false_type {};
  95. template <typename T>
  96. struct IsTuple<EnableIfTuple<T>, T> : std::true_type {};
  97. /**
  98. * Check if the sequence is a range
  99. */
  100. template <typename Type, typename T = typename std::decay<Type>::type>
  101. using EnableIfRange = void_t<
  102. decltype(adl::adl_begin(std::declval<T>())),
  103. decltype(adl::adl_end(std::declval<T>()))>;
  104. template <typename, typename T>
  105. struct IsRange : std::false_type {};
  106. template <typename T>
  107. struct IsRange<EnableIfRange<T>, T> : std::true_type {};
  108. struct TupleTag {};
  109. struct RangeTag {};
  110. /**
  111. * Should ideally check if it is a tuple and if not return void, but msvc fails
  112. */
  113. template <typename Sequence>
  114. using SequenceTag =
  115. std::conditional_t<IsRange<void, Sequence>::value, RangeTag, TupleTag>;
  116. struct BeginAddTag {};
  117. struct IndexingTag {};
  118. template <typename Func, typename Item, typename Iter>
  119. using ForEachImplTag = std::conditional_t<
  120. is_invocable<Func, Item, index_constant<0>, Iter>::value,
  121. index_constant<3>,
  122. std::conditional_t<
  123. is_invocable<Func, Item, index_constant<0>>::value,
  124. index_constant<2>,
  125. std::conditional_t<
  126. is_invocable<Func, Item>::value,
  127. index_constant<1>,
  128. void>>>;
  129. template <
  130. typename Func,
  131. typename... Args,
  132. std::enable_if_t<is_invocable_r<LoopControl, Func, Args...>::value, int> =
  133. 0>
  134. LoopControl invoke_returning_loop_control(Func&& f, Args&&... a) {
  135. return static_cast<Func&&>(f)(static_cast<Args&&>(a)...);
  136. }
  137. template <
  138. typename Func,
  139. typename... Args,
  140. std::enable_if_t<!is_invocable_r<LoopControl, Func, Args...>::value, int> =
  141. 0>
  142. LoopControl invoke_returning_loop_control(Func&& f, Args&&... a) {
  143. static_assert(
  144. std::is_void<invoke_result_t<Func, Args...>>::value,
  145. "return either LoopControl or void");
  146. return static_cast<Func&&>(f)(static_cast<Args&&>(a)...), loop_continue;
  147. }
  148. /**
  149. * Implementations for the runtime function
  150. */
  151. template <typename Sequence, typename Func>
  152. void for_each_range_impl(index_constant<3>, Sequence&& range, Func& func) {
  153. auto first = adl::adl_begin(range);
  154. auto last = adl::adl_end(range);
  155. for (auto index = std::size_t{0}; first != last; ++index) {
  156. auto next = std::next(first);
  157. auto control = invoke_returning_loop_control(func, *first, index, first);
  158. if (loop_break == control) {
  159. break;
  160. }
  161. first = next;
  162. }
  163. }
  164. template <typename Sequence, typename Func>
  165. void for_each_range_impl(index_constant<2>, Sequence&& range, Func& func) {
  166. // make a three arg adaptor for the function passed in so that the main
  167. // implementation function can be used
  168. auto three_arg_adaptor = [&func](
  169. auto&& ele, auto index, auto) -> decltype(auto) {
  170. return func(std::forward<decltype(ele)>(ele), index);
  171. };
  172. for_each_range_impl(
  173. index_constant<3>{}, std::forward<Sequence>(range), three_arg_adaptor);
  174. }
  175. template <typename Sequence, typename Func>
  176. void for_each_range_impl(index_constant<1>, Sequence&& range, Func& func) {
  177. // make a three argument adaptor for the function passed in that just ignores
  178. // the second and third argument
  179. auto three_arg_adaptor = [&func](auto&& ele, auto, auto) -> decltype(auto) {
  180. return func(std::forward<decltype(ele)>(ele));
  181. };
  182. for_each_range_impl(
  183. index_constant<3>{}, std::forward<Sequence>(range), three_arg_adaptor);
  184. }
  185. /**
  186. * Handlers for iteration
  187. */
  188. template <typename Sequence, typename Func, std::size_t... Indices>
  189. void for_each_tuple_impl(
  190. index_sequence<Indices...>,
  191. Sequence&& seq,
  192. Func& func) {
  193. using _ = int[];
  194. // unroll the loop in an initializer list construction parameter expansion
  195. // pack
  196. auto control = loop_continue;
  197. // cast to void to ignore the result; use the int[] initialization to do the
  198. // loop execution, the ternary conditional will decide whether or not to
  199. // evaluate the result
  200. //
  201. // if func does not return loop-control, expect the optimizer to see through
  202. // invoke_returning_loop_control always returning loop_continue
  203. void(
  204. _{(((control == loop_continue)
  205. ? (control = invoke_returning_loop_control(
  206. func,
  207. get_impl<Indices>(std::forward<Sequence>(seq)),
  208. index_constant<Indices>{}))
  209. : (loop_continue)),
  210. 0)...});
  211. }
  212. /**
  213. * The two top level compile time loop iteration functions handle the dispatch
  214. * based on the number of arguments the passed in function can be passed, if 2
  215. * arguments can be passed then the implementation dispatches work further to
  216. * the implementation classes above. If not then an adaptor is constructed
  217. * which is passed on to the 2 argument specialization, which then in turn
  218. * forwards implementation to the implementation classes above
  219. */
  220. template <typename Sequence, typename Func>
  221. void for_each_tuple_impl(index_constant<2>, Sequence&& seq, Func& func) {
  222. // pass the length as an index sequence to the implementation as an
  223. // optimization over manual template "tail recursion" unrolling
  224. using size = std::tuple_size<typename std::decay<Sequence>::type>;
  225. for_each_tuple_impl(
  226. make_index_sequence<size::value>{}, std::forward<Sequence>(seq), func);
  227. }
  228. template <typename Sequence, typename Func>
  229. void for_each_tuple_impl(index_constant<1>, Sequence&& seq, Func& func) {
  230. // make an adaptor for the function passed in, in case it can only be passed
  231. // on argument
  232. auto two_arg_adaptor = [&func](auto&& ele, auto) -> decltype(auto) {
  233. return func(std::forward<decltype(ele)>(ele));
  234. };
  235. for_each_tuple_impl(
  236. index_constant<2>{}, std::forward<Sequence>(seq), two_arg_adaptor);
  237. }
  238. /**
  239. * Top level handlers for the for_each loop, with one overload for tuples and
  240. * one overload for ranges
  241. *
  242. * This implies that if type is both a range and a tuple, it is treated as a
  243. * range rather than as a tuple
  244. */
  245. template <typename Sequence, typename Func>
  246. static void for_each_impl(TupleTag, Sequence&& range, Func& func) {
  247. using type = decltype(get_impl<0>(std::declval<Sequence>()));
  248. using tag = ForEachImplTag<Func, type, void>;
  249. static_assert(!std::is_same<tag, void>::value, "unknown invocability");
  250. for_each_tuple_impl(tag{}, std::forward<Sequence>(range), func);
  251. }
  252. template <typename Sequence, typename Func>
  253. static void for_each_impl(RangeTag, Sequence&& range, Func& func) {
  254. using iter = decltype(adl::adl_begin(std::declval<Sequence>()));
  255. using type = decltype(*std::declval<iter>());
  256. using tag = ForEachImplTag<Func, type, iter>;
  257. static_assert(!std::is_same<tag, void>::value, "unknown invocability");
  258. for_each_range_impl(tag{}, std::forward<Sequence>(range), func);
  259. }
  260. template <typename Sequence, typename Index>
  261. decltype(auto) fetch_impl(IndexingTag, Sequence&& sequence, Index&& index) {
  262. return std::forward<Sequence>(sequence)[std::forward<Index>(index)];
  263. }
  264. template <typename Sequence, typename Index>
  265. decltype(auto) fetch_impl(BeginAddTag, Sequence&& sequence, Index index) {
  266. return *(adl::adl_begin(std::forward<Sequence>(sequence)) + index);
  267. }
  268. template <typename Sequence, typename Index>
  269. decltype(auto) fetch_impl(TupleTag, Sequence&& sequence, Index index) {
  270. return get_impl<index>(std::forward<Sequence>(sequence));
  271. }
  272. template <typename Sequence, typename Index>
  273. decltype(auto) fetch_impl(RangeTag, Sequence&& sequence, Index&& index) {
  274. using iter = decltype(adl::adl_begin(std::declval<Sequence>()));
  275. using iter_traits = std::iterator_traits<remove_cvref_t<iter>>;
  276. using iter_cat = typename iter_traits::iterator_category;
  277. using tag = std::conditional_t<
  278. std::is_same<iter_cat, std::random_access_iterator_tag>::value,
  279. BeginAddTag,
  280. IndexingTag>;
  281. return fetch_impl(
  282. tag{}, std::forward<Sequence>(sequence), std::forward<Index>(index));
  283. }
  284. } // namespace for_each_detail
  285. template <typename Sequence, typename Func>
  286. FOLLY_CPP14_CONSTEXPR Func for_each(Sequence&& sequence, Func func) {
  287. namespace fed = for_each_detail;
  288. using tag = fed::SequenceTag<Sequence>;
  289. fed::for_each_impl(tag{}, std::forward<Sequence>(sequence), func);
  290. return func;
  291. }
  292. template <typename Sequence, typename Index>
  293. FOLLY_CPP14_CONSTEXPR decltype(auto) fetch(Sequence&& sequence, Index&& index) {
  294. namespace fed = for_each_detail;
  295. using tag = fed::SequenceTag<Sequence>;
  296. return for_each_detail::fetch_impl(
  297. tag{}, std::forward<Sequence>(sequence), std::forward<Index>(index));
  298. }
  299. } // namespace folly