Макрос для цикла итератора для итераций STL

концепция

так, я пытаюсь определить макрос, чтобы упростить следующий код:

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

и

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

etc.

Существующие Работы

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

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

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

цель

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

for (every(iter, iterable))

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

условия

  • это, в идеале, должно войти в (относительно) большую кодовую базу, уже настроенную для доступа к

6 ответов


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

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

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


Если вы используете 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.


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

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

edit:

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

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

затем реализовать:

for(every(iter, iterable))
{
    UseElement(*iter);
}

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

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)
{
}

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

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, но в этом случае он не может использоваться вне шаблонной функции.