/* Copyright (c) 2004..2011 Dirk Jagdmann This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ // $Header: /home/doj/a/www/llg/docs/foreach.hpp,v 1.2 2011-03-20 19:00:52 doj Exp $ #ifndef FOREACH__HPP #define FOREACH__HPP #if defined(__GNUC__) && __GNUC__==4 && __GNUC_MINOR__<4 #define FOREACH__HPP_TYPEOF 1 #elif defined(__GNUC__) && __GNUC__==4 && __GNUC_MINOR__>=4 #define FOREACH__HPP_AUTO 1 #elif defined(_MSC_VER) && _MSC_VER<1600 #include #define FOREACH__HPP_TYPEOF 1 #define __typeof__(ex) BOOST_TYPEOF(ex) #elif defined(_MSC_VER) && _MSC_VER>=1600 #define FOREACH__HPP_AUTO 1 #else #error unknown compiler! #endif #if defined(FOREACH__HPP_TYPEOF) #ifndef foreach /** a for loop to iterate over a container. @param c (STL) container, has to support begin() and end() methods. @param i name of iterator which is available in loop body. */ #define foreach(c,i) for(/*lint --e{953}*/__typeof__((c).begin()) i = (c).begin(), end##i = (c).end(); i != end##i; ++i) #endif #ifndef foreach_r /** a for loop to iterate over a container in reverse direction. @param c (STL) container, has to support rbegin() and rend() methods. @param i name of reverse iterator which is available in loop body. */ #define foreach_r(c,i) for(/*lint --e{953}*/__typeof__((c).rbegin()) i = (c).rbegin(), end##i = (c).rend(); i != end##i; ++i) #endif #ifndef foreach_e /** a for loop to iterate over a container. You can call erase() on i if the erase() function does not invalidate iterators different from i. This is true for STL map, multimap, set, multiset. See https://llg.cubic.org/docs/stlerase.html for details. @param c (STL) container, has to support begin() and end() methods. @param i name of iterator which is available in loop body */ #define foreach_e(c,i) for(/*lint --e{953}*/__typeof__((c).end()) end##i = (c).end(), \ next##i = (c).begin(), \ i = (next##i==end##i)?next##i:next##i++; \ i != next##i; \ i = (next##i==end##i)?next##i:next##i++) #endif #elif defined(FOREACH__HPP_AUTO) #define foreach(c,i) for(auto i = (c).begin(), end##i = (c).end(); i != end##i; ++i) #define foreach_r(c,i) for(auto i = (c).rbegin(), end##i = (c).rend(); i != end##i; ++i) #define foreach_e(c,i) for(auto end##i = (c).end(), next##i = (c).begin(), i = (next##i==end##i)?next##i:next##i++; \ i != next##i; \ i = (next##i==end##i)?next##i:next##i++) #else #error no code style defined! #endif #ifdef TESTFOREACH #include #include #include #include #include #include // random generator ripped from http://en.wikipedia.org/wiki/Random_number_generation unsigned get_random() { static unsigned m_w = 31337; static unsigned m_z = 123456789^0xdeadbeef; m_z = 36969 * (m_z & 65535) + (m_z >> 16); m_w = 18000 * (m_w & 65535) + (m_w >> 16); return (m_z << 16) + m_w; /* 32-bit result */ } int main() { std::set > d; for(int k=0; k!=10; ++k) { std::vector v; for(int j=0; j!=10; ++j) { std::string s; for(int i=0; i!=10; ++i) s+='0'+(get_random()%10); v.push_back(s); } d.insert(v); } std::string test; foreach(d, D) foreach(*D, V) foreach(*V, c) test+=*c; //std::cout << test << std::endl; assert(test == "1808093332198863506372251418969364191391145708304909790930777894405001030373984284727671133434117144235225169794657014345347047834901676997783295112587335934245588093037177012357628750295871909482501029524972715667739485612387035465017321532143610619017637276133189027163129805742377530833156542041883430650782730331595528499380066656911115819653456415336555325639240549800650845751283674280616657407371764322594915831583971524001117174675686280427166051571598679118790698740715736955911296720167084040280940033369515639390199145849619251592161032438849310121459538261288108527336323506253014292416756248581687966738537843753446764645024747444521156913988896904933475882012700125686669317124290959937654060469159531674359103767468177951347590000712924993675321047706280031907898829206997116665257816270463229153186528560672871929666060192267125852773391021605130735406457844634384547564717161374347547925657440682925601482007364126693701344449458991217158378156917701437299678790606638525398179199918"); typedef std::map m_t; m_t m; m[0]=0; m[1]=1; m[2]=2; m[3]=3; m[4]=4; m[5]=5; m[6]=6; m[7]=7; m[8]=8; m[9]=9; foreach_e(m, it) if(it->first & 1) m.erase(it); assert(m.size() == 5); foreach_e(m, it) m.erase(it); assert(m.empty()); std::cout << "foreach succeed.\n"; return 0; } #endif // TESTFOREACH #endif // FOREACH__HPP