В Qt существует цикл foreach, который реализуется с использованием макросов (Q_FOREACH). Существуют различные реализации, в зависимости от компилятора.
Определение для GCC выглядит следующим образом:
#define Q_FOREACH(variable, container) \
for (QForeachContainer<__typeof__(container)> _container_(container); \
!_container_.brk && _container_.i != _container_.e; \
__extension__ ({ ++_container_.brk; ++_container_.i; })) \
for (variable = *_container_.i;; __extension__ ({--_container_.brk; break;}))
... используя вспомогательный класс QForeachContainer, который определяется следующим образом:
template <typename T>
class QForeachContainer {
public:
inline QForeachContainer(const T& t) : c(t), brk(0), i(c.begin()), e(c.end()) { }
const T c;
int brk;
typename T::const_iterator i, e;
};
Контейнер в макросе Q_FOREACH должен быть классом T, который, по крайней мере, должен предоставить тип T::const_iterator, T.begin() и T.end(), как и все контейнеры STL, а также большинство контейнеров Qt, таких как QList, QVector, QMap, QHash,...
Теперь мой вопрос: Как работает этот макрос?
Одна вещь кажется очень странной: переменная появляется только один раз в определении макроса. Так, например, foreach(QString item, list) имеет a QString item =, но no item = после этого в любое время... Как можно изменить переменную item на каждом шаге?
Еще более запутанным является следующее определение Q_FOREACH для компилятора MS VС++:
#define Q_FOREACH(variable,container) \
if(0){}else \
for (const QForeachContainerBase &_container_ = qForeachContainerNew(container); \
qForeachContainer(&_container_, true ? 0 : qForeachPointer(container))->condition(); \
++qForeachContainer(&_container_, true ? 0 : qForeachPointer(container))->i) \
for (variable = *qForeachContainer(&_container_, true ? 0 : qForeachPointer(container))->i; \
qForeachContainer(&_container_, true ? 0 : qForeachPointer(container))->brk; \
--qForeachContainer(&_container_, true ? 0 : qForeachPointer(container))->brk)
Почему true : 0 ? ...? Разве это не всегда оценивается как 0? Выполняется ли вызов функции qForeachPointer(container), даже если условие до ? истинно?
И зачем нам нужны два for-loops?
Было бы здорово, если бы кто-нибудь мог сделать что-то более понятное для меня!