Макрос для цикла итераторов для итераций STL - PullRequest
7 голосов
/ 09 декабря 2011

Концепция

Итак, я пытаюсь определить макрос для упрощения следующего кода:

for (vector<TYPE>::iterator iter = iterable.begin(); 
             iter != iterable.end(); iter++)

и

for (map<TYPE, TYPE>::iterator iter = iterable.begin();
             iter != iterable.end(); iter++)

и т. Д.

Существующая работа

Пока у меня есть

#define every(iter, iterable) ::iterator iter = iterable.begin(); iter != iterable.end(); iter++
for (vector<TYPE> every(iter, iterable))

, но я бы хотел еще больше упростить это.

Цель

В идеале я бы хотел иметь возможность

for (every(iter, iterable))

, что означает, что мне нужно каким-то образом получить class<TYPE> повторяемого объекта.Это возможно?Если да, то как я могу это сделать?

Stipulations

  • В идеале это должно включать (относительно) большую кодовую базу, уже настроенную для доступа к объекту iterator.
  • Я работаю на компиляторе предварительно - C ++ 11

Victory

#define every(iter, iterable) typeof(iterable.begin()) iter = iterable.begin(); iter != iterable.end(); iter++
for (every(iter, iterable))

Ответы [ 6 ]

8 голосов
/ 09 декабря 2011

Этот ответ не зависит от C ++ 11, но ему требуется typeof, которого могут не иметь некоторые компиляторы.Должен работать с любым последним g ++

#define For(iter, iterable) for(typeof((iterable).begin()) iter = (iterable).begin(); iter != (iterable).end(); ++iter)
2 голосов
/ 23 декабря 2011

Если вы используете C ++ 11, вы можете использовать новый для синтаксиса.

vector<double> v(9, 0.5);
auto total = 0.;
for (auto x: v) {
    total += x;
}

Если вам нужна ссылка для изменения значений, вы можете использовать:

vector<double> v(9, 0.5);
for (auto &x: v) {
    x = 5;
}

Просто скомпилируйте с флагом -std = c ++ 0x.

2 голосов
/ 09 декабря 2011

Вы можете использовать for(auto iter = iterable.being(); iter != iterable.end(); iter++), если ваш компилятор поддерживает C ++ 0x.

1 голос
/ 09 декабря 2011

Если вы используете c ++ 11, тогда используйте auto!

for (auto it = vec.begin(); it != vec.end(); it++)
{
}

редактирование:

Это будет ваш макрос:

#define every(iter, iterable) auto iter = iterable.begin(); iter != iterable.end(); iter++

Тогда имплментация:

for(every(iter, iterable))
{
    UseElement(*iter);
}
0 голосов
/ 25 февраля 2015

Я хотел бы расширить довольно хороший ответ Аарона МакДейда. Я нашел очень похожее решение в среде до C ++ 0x (я назвал макрос как FOREACH). Это работает для нормальных iterator и reverse iterator. Но как это можно сделать на const_iterator и const_reverse_iterator? К сожалению, cbegin() является функцией C ++ 0x, а typeof(container)::const_iterator не работает. Очень маленький шаблонный класс может решить проблему. Вот мой код:

template <class T>
struct IterType { typedef typename T::const_iterator citer_t; };

#define FOREACHCONST(_CIter, _Container) \
  for(IterType<typeof(_Container)>::citer_t _CIter = (_Container).begin(); \
      _CIter != (_Container).end(); ++_CIter )

Он работает точно так же, как FOREACH.

Интересно, что это не работает внутри шаблонной функции. В этом случае ключевое слово typename должно быть добавлено непосредственно перед IterType, но в этом случае оно не может использоваться вне шаблонной функции.

0 голосов
/ 09 декабря 2011

Почему бы просто не использовать std :: for_each? В C ++ 11 вы можете использовать их с лямбдами.

C ++ 11 также имеет базовый цикл диапазона.

template<typename T>
void Foo(const T& x)
{
    for (auto& i : x)
        std::cout << i << std::endl;
}

Конечно, обязательно ... МАКРО ЗЛО

Если вы застряли с древним компилятором, вы всегда можете сделать

typedef std::map<int,int> IntMap_t;
IntMap_t tmap;
for( IntMap_t::iterator iter = tmap.begin();
         iter != tmap.end();
         ++iter)
{
}
...