В 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?
Было бы здорово, если бы кто-нибудь мог сделать что-то более понятное для меня!