// This code is in the public domain -- Ignacio Castaņo #pragma once #ifndef NV_CORE_FOREACH_H #define NV_CORE_FOREACH_H /* These foreach macros are very non-standard and somewhat confusing, but I like them. */ #include "nvcore.h" #if NV_CC_GNUC || NV_CC_CPP11 // If typeof or decltype is available: #if !NV_CC_CPP11 # define NV_DECLTYPE typeof // Using a non-standard extension over typeof that behaves as C++11 decltype #else # define NV_DECLTYPE decltype #endif #define NV_FOREACH(i, container) \ typedef NV_DECLTYPE(container) NV_STRING_JOIN2(cont,__LINE__); \ for(NV_STRING_JOIN2(cont,__LINE__)::PseudoIndex i((container).start()); !(container).isDone(i); (container).advance(i)) /* #define NV_FOREACH(i, container) \ for(typename typeof(container)::PseudoIndex i((container).start()); !(container).isDone(i); (container).advance(i)) */ #else // If typeof not available: #include // placement new struct PseudoIndexWrapper { template PseudoIndexWrapper(const T & container) { nvStaticCheck(sizeof(typename T::PseudoIndex) <= sizeof(memory)); new (memory) typename T::PseudoIndex(container.start()); } // PseudoIndex cannot have a dtor! template typename T::PseudoIndex & operator()(const T * /*container*/) { return *reinterpret_cast(memory); } template const typename T::PseudoIndex & operator()(const T * /*container*/) const { return *reinterpret_cast(memory); } uint8 memory[4]; // Increase the size if we have bigger enumerators. }; #define NV_FOREACH(i, container) \ for(PseudoIndexWrapper i(container); !(container).isDone(i(&(container))); (container).advance(i(&(container)))) #endif // Declare foreach keyword. #if !defined NV_NO_USE_KEYWORDS # define foreach NV_FOREACH # define foreach_index NV_FOREACH #endif #endif // NV_CORE_FOREACH_H