From fbcd8169fb3c92878792591bac886e891bc7cdfd Mon Sep 17 00:00:00 2001 From: Phil Willoughby Date: Mon, 19 Jun 2017 05:51:34 -0700 Subject: [PATCH] Document the preferred alternatives in Foreach.h Reviewed By: yfeldblum Differential Revision: D5228760 fbshipit-source-id: bcad4237997e611e06c93b476c5b673dc93c0621 --- folly/Foreach.h | 101 +++++++++++++++++++++--------------------------- 1 file changed, 45 insertions(+), 56 deletions(-) diff --git a/folly/Foreach.h b/folly/Foreach.h index 5cc075c7..3ea9b3a4 100644 --- a/folly/Foreach.h +++ b/folly/Foreach.h @@ -16,38 +16,19 @@ #pragma once -/* - * Iterim macros (until we have C++0x range-based for) that simplify - * writing loops of the form - * - * for (Container::iterator i = c.begin(); i != c.end(); ++i) statement - * - * Just replace the above with: - * - * FOR_EACH (i, c) statement - * - * and everything is taken care of. +/** + * This header is deprecated * - * The implementation is a bit convoluted to make sure the container is - * evaluated only once (however, keep in mind that c.end() is evaluated - * at every pass through the loop). To ensure the container is not - * evaluated multiple times, the macro defines one do-nothing if - * statement to inject the Boolean variable FOR_EACH_state1, and then a - * for statement that is executed only once, which defines the variable - * FOR_EACH_state2 holding an rvalue reference to the container being - * iterated. The workhorse is the last loop, which uses the just-defined - * rvalue reference FOR_EACH_state2. + * Use range-based for loops, and if necessary Ranges-v3. * - * The state variables are nested so they don't interfere; you can use - * FOR_EACH multiple times in the same scope, either at the same level or - * nested. + * Some of the messaging here presumes that you have coded: * - * In optimized builds g++ eliminates the extra gymnastics entirely and - * generates code 100% identical to the handwritten loop. + * #include + * using namespace ranges; */ -#include #include +#include /* * Form a local variable name from "FOR_EACH_" x __LINE__, so that @@ -56,9 +37,11 @@ #define _FE_ANON(x) FB_CONCATENATE(FOR_EACH_, FB_CONCATENATE(x, __LINE__)) /* - * Shorthand for: - * for (auto i = c.begin(); i != c.end(); ++i) - * except that c is evaluated only once. + * If you just want the element values, please use: + * + * for (auto&& element : collection) + * + * If you need access to the iterators please write an explicit iterator loop */ #define FOR_EACH(i, c) \ if (bool _FE_ANON(s1_) = false) {} else \ @@ -68,8 +51,11 @@ i != _FE_ANON(s2_).end(); ++i) /* - * Similar to FOR_EACH, but iterates the container backwards by - * using rbegin() and rend(). + * If you just want the element values, please use this (ranges-v3) construct: + * + * for (auto&& element : collection | view::reverse) + * + * If you need access to the iterators please write an explicit iterator loop */ #define FOR_EACH_R(i, c) \ if (bool _FE_ANON(s1_) = false) {} else \ @@ -79,13 +65,12 @@ i != _FE_ANON(s2_).rend(); ++i) /* - * Similar to FOR_EACH but also allows client to specify a 'count' variable - * to track the current iteration in the loop (starting at zero). - * Similar to python's enumerate() function. For example: - * string commaSeparatedValues = "VALUES: "; - * FOR_EACH_ENUMERATE(ii, value, columns) { // don't want comma at the end! - * commaSeparatedValues += (ii == 0) ? *value : string(",") + *value; - * } + * If you just want the element values, please use this (ranges-v3) construct: + * + * for (auto&& element : collection | view::zip(view::ints)) + * + * If you need access to the iterators please write an explicit iterator loop + * and use a counter variable */ #define FOR_EACH_ENUMERATE(count, i, c) \ if (bool _FE_ANON(s1_) = false) {} else \ @@ -95,14 +80,23 @@ if (const size_t& count = _FE_ANON(n1_)) {} else \ for (auto i = FOR_EACH_state2.begin(); \ i != FOR_EACH_state2.end(); ++_FE_ANON(n1_), ++i) - /** - * Similar to FOR_EACH, but gives the user the key and value for each entry in - * the container, instead of just the iterator to the entry. For example: - * map testMap; - * FOR_EACH_KV(key, value, testMap) { - * cout << key << " " << value; - * } + * If you just want the keys, please use this (ranges-v3) construct: + * + * for (auto&& element : collection | view::keys) + * + * If you just want the values, please use this (ranges-v3) construct: + * + * for (auto&& element : collection | view::values) + * + * If you need to see both, use: + * + * for (auto&& element : collection) { + * auto const& key = element.first; + * auto& value = element.second; + * ...... + * } + * */ #define FOR_EACH_KV(k, v, c) \ if (unsigned int _FE_ANON(s1_) = 0) {} else \ @@ -210,12 +204,10 @@ downTo(T& iter, const U& begin) { } } /* - * Iteration with given limits. end is assumed to be reachable from - * begin. end is evaluated every pass through the loop. + * Look at the Ranges-v3 views and you'll probably find an easier way to build + * the view you want but the equivalent is roughly: * - * NOTE: The type of the loop variable should be the common type of "begin" - * and "end". e.g. If "begin" is "int" but "end" is "long", we want "i" - * to be "long". This is done by getting the type of (true ? begin : end) + * for (auto& element : make_iterator_range(begin, end)) */ #define FOR_EACH_RANGE(i, begin, end) \ for (auto i = (true ? (begin) : (end)); \ @@ -223,13 +215,10 @@ downTo(T& iter, const U& begin) { ++i) /* - * Iteration with given limits. begin is assumed to be reachable from - * end by successive decrements. begin is evaluated every pass through - * the loop. + * Look at the Ranges-v3 views and you'll probably find an easier way to build + * the view you want but the equivalent is roughly: * - * NOTE: The type of the loop variable should be the common type of "begin" - * and "end". e.g. If "begin" is "int" but "end" is "long", we want "i" - * to be "long". This is done by getting the type of (false ? begin : end) + * for (auto& element : make_iterator_range(begin, end) | view::reverse) */ #define FOR_EACH_RANGE_R(i, begin, end) \ for (auto i = (false ? (begin) : (end)); ::folly::detail::downTo(i, (begin));) -- 2.34.1