В 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)
имеет QString item =
, но не item =
впоследствии в любое время... Как тогда переменная item
может изменяться на каждом шаге?
Еще более запутанным является следующее определениеQ_FOREACH
для компилятора MS VC++:
#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 -?
Было бы здорово, если бы кто-нибудь мог сделать вещи немного яснее для меня!