X-Git-Url: http://plrg.eecs.uci.edu/git/?p=folly.git;a=blobdiff_plain;f=folly%2FForeach.h;h=5cc075c7e6aeeeeeb4a476a091da42bfa72e734a;hp=eb11d0a478a3b7069a2dd4c329b51e9abca988ee;hb=3e09d2ba6b89eb0ce684fbb0ffcb9c95b557061a;hpb=d64c6e0d5b27374a6116fc1d69ae17d620dfabec diff --git a/folly/Foreach.h b/folly/Foreach.h index eb11d0a4..5cc075c7 100644 --- a/folly/Foreach.h +++ b/folly/Foreach.h @@ -1,5 +1,5 @@ /* - * Copyright 2013 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. @@ -14,8 +14,7 @@ * 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 @@ -30,13 +29,13 @@ * 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 rvalue reference to the container being - * iterated. The workhorse is the last loop, which uses the just defined + * 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 @@ -47,30 +46,37 @@ * generates code 100% identical to the handwritten loop. */ -#include +#include +#include + +/* + * Form a local variable name from "FOR_EACH_" x __LINE__, so that + * FOR_EACH can be nested without creating shadowed declarations. + */ +#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 only evaluated once. + * except that c is evaluated only once. */ -#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 @@ -82,13 +88,13 @@ * } */ #define FOR_EACH_ENUMERATE(count, i, c) \ - if (bool FOR_EACH_state1 = false) {} else \ + if (bool _FE_ANON(s1_) = 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 \ + !_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 @@ -98,19 +104,19 @@ * cout << key << " " << value; * } */ -#define FOR_EACH_KV(k, v, c) \ - if (unsigned int FOR_EACH_state1 = 0) {} else \ - for (auto && 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 { @@ -227,5 +233,3 @@ downTo(T& iter, const U& begin) { */ #define FOR_EACH_RANGE_R(i, begin, end) \ for (auto i = (false ? (begin) : (end)); ::folly::detail::downTo(i, (begin));) - -#endif