Как работает макрос Q _FOREACH (= foreach )и почему он такой сложный?

В 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 -?

Было бы здорово, если бы кто-нибудь мог сделать вещи немного яснее для меня!

35
задан leemes 22 January 2013 в 13:26
поделиться