/*
- * Copyright 2012 Facebook, Inc.
+ * Copyright 2017 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* limitations under the License.
*/
-#ifndef FOLLY_BASE_FOREACH_H_
-#define FOLLY_BASE_FOREACH_H_
+#pragma once
/*
* Iterim macros (until we have C++0x range-based for) that simplify
* and everything is taken care of.
*
* The implementation is a bit convoluted to make sure the container is
- * only evaluated once (however, keep in mind that c.end() is evaluated
+ * 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 a reference to the container being
- * iterated. The workhorse is the last loop, which uses the just defined
- * reference FOR_EACH_state2.
+ * 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.
*
* 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
*
* In optimized builds g++ eliminates the extra gymnastics entirely and
* generates code 100% identical to the handwritten loop.
- *
- * This will not work with temporary containers. Consider BOOST_FOREACH
- * if you need that.
*/
-#include <boost/type_traits/remove_cv.hpp>
-
-namespace folly { namespace detail {
+#include <type_traits>
+#include <folly/Preprocessor.h>
/*
- * Simple template for obtaining the unqualified type given a generic
- * type T. For example, if T is const int,
- * typeof(remove_cv_from_expression(T())) yields int. Due to a bug in
- * g++, you need to actually use
- * typeof(remove_cv_from_expression(T())) instead of typename
- * boost::remove_cv<T>::type. Note that the function
- * remove_cv_from_expression is never defined - use it only inside
- * typeof.
+ * Form a local variable name from "FOR_EACH_" x __LINE__, so that
+ * FOR_EACH can be nested without creating shadowed declarations.
*/
-template <class T> typename boost::remove_cv<T>::type
-remove_cv_from_expression(T value);
-
-}}
+#define _FE_ANON(x) FB_CONCATENATE(FOR_EACH_, FB_CONCATENATE(x, __LINE__))
/*
- * Use a "reference reference" (auto&&) to take advantage of reference
- * collapsing rules, if available. In this case, FOR_EACH* will work with
- * temporary containers.
+ * Shorthand for:
+ * for (auto i = c.begin(); i != c.end(); ++i)
+ * except that c is evaluated only once.
*/
-#define FB_AUTO_RR(x, y) auto&& x = y
-
-/*
- * The first AUTO should be replaced by decltype((c)) &
- * FOR_EACH_state2, but bugs in gcc prevent that from functioning
- * properly. The second pair of parens in decltype is actually
- * required, see
- * cpp-next.com/archive/2011/04/appearing-and-disappearing-consts-in-c/
- */
-#define FOR_EACH(i, c) \
- if (bool FOR_EACH_state1 = false) {} else \
- for (auto & FOR_EACH_state2 = (c); \
- !FOR_EACH_state1; FOR_EACH_state1 = true) \
- for (auto i = FOR_EACH_state2.begin(); \
- i != FOR_EACH_state2.end(); ++i)
+#define FOR_EACH(i, c) \
+ if (bool _FE_ANON(s1_) = false) {} else \
+ for (auto && _FE_ANON(s2_) = (c); \
+ !_FE_ANON(s1_); _FE_ANON(s1_) = true) \
+ for (auto i = _FE_ANON(s2_).begin(); \
+ i != _FE_ANON(s2_).end(); ++i)
/*
* Similar to FOR_EACH, but iterates the container backwards by
* using rbegin() and rend().
*/
#define FOR_EACH_R(i, c) \
- if (bool FOR_EACH_R_state1 = false) {} else \
- for (auto & FOR_EACH_R_state2 = (c); \
- !FOR_EACH_R_state1; FOR_EACH_R_state1 = true) \
- for (auto i = FOR_EACH_R_state2.rbegin(); \
- i != FOR_EACH_R_state2.rend(); ++i)
+ if (bool _FE_ANON(s1_) = false) {} else \
+ for (auto && _FE_ANON(s2_) = (c); \
+ !_FE_ANON(s1_); _FE_ANON(s1_) = true) \
+ for (auto i = _FE_ANON(s2_).rbegin(); \
+ i != _FE_ANON(s2_).rend(); ++i)
/*
* Similar to FOR_EACH but also allows client to specify a 'count' variable
* }
*/
#define FOR_EACH_ENUMERATE(count, i, c) \
- if (bool FOR_EACH_state1 = false) {} else \
- for (auto & FOR_EACH_state2 = (c); \
- !FOR_EACH_state1; FOR_EACH_state1 = true) \
- if (size_t FOR_EACH_privateCount = 0) {} else \
- if (const size_t& count = FOR_EACH_privateCount) {} else \
+ if (bool _FE_ANON(s1_) = false) {} else \
+ for (auto && FOR_EACH_state2 = (c); \
+ !_FE_ANON(s1_); _FE_ANON(s1_) = true) \
+ if (size_t _FE_ANON(n1_) = 0) {} else \
+ if (const size_t& count = _FE_ANON(n1_)) {} else \
for (auto i = FOR_EACH_state2.begin(); \
- i != FOR_EACH_state2.end(); ++FOR_EACH_privateCount, ++i)
+ 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
* cout << key << " " << value;
* }
*/
-#define FOR_EACH_KV(k, v, c) \
- if (unsigned int FOR_EACH_state1 = 0) {} else \
- for (FB_AUTO_RR(FOR_EACH_state2, (c)); \
- !FOR_EACH_state1; FOR_EACH_state1 = 1) \
- for (auto FOR_EACH_state3 = FOR_EACH_state2.begin(); \
- FOR_EACH_state3 != FOR_EACH_state2.end(); \
- FOR_EACH_state1 == 2 \
- ? ((FOR_EACH_state1 = 0), ++FOR_EACH_state3) \
- : (FOR_EACH_state3 = FOR_EACH_state2.end())) \
- for (auto &k = FOR_EACH_state3->first; \
- !FOR_EACH_state1; ++FOR_EACH_state1) \
- for (auto &v = FOR_EACH_state3->second; \
- !FOR_EACH_state1; ++FOR_EACH_state1)
+#define FOR_EACH_KV(k, v, c) \
+ if (unsigned int _FE_ANON(s1_) = 0) {} else \
+ for (auto && _FE_ANON(s2_) = (c); \
+ !_FE_ANON(s1_); _FE_ANON(s1_) = 1) \
+ for (auto _FE_ANON(s3_) = _FE_ANON(s2_).begin(); \
+ _FE_ANON(s3_) != _FE_ANON(s2_).end(); \
+ _FE_ANON(s1_) == 2 \
+ ? ((_FE_ANON(s1_) = 0), ++_FE_ANON(s3_)) \
+ : (_FE_ANON(s3_) = _FE_ANON(s2_).end())) \
+ for (auto &k = _FE_ANON(s3_)->first; \
+ !_FE_ANON(s1_); ++_FE_ANON(s1_)) \
+ for (auto &v = _FE_ANON(s3_)->second; \
+ !_FE_ANON(s1_); ++_FE_ANON(s1_))
namespace folly { namespace detail {
*/
#define FOR_EACH_RANGE_R(i, begin, end) \
for (auto i = (false ? (begin) : (end)); ::folly::detail::downTo(i, (begin));)
-
-#endif