Visual C ++ «для каждой» мобильности - PullRequest
23 голосов
/ 13 октября 2008

Я только недавно обнаружил, что Visual C ++ 2008 (и, возможно, также более ранние версии?) Поддерживает синтаксис for each в списках stl и др. Для облегчения итерации. Например:

list<Object> myList;

for each (Object o in myList)
{
  o.foo();
}

Я был очень счастлив обнаружить это, но меня беспокоит переносимость в тот страшный день, когда кто-то решит, что мне нужно иметь возможность скомпилировать мой код, скажем, в gcc или каком-то другом компиляторе. Широко ли поддерживается этот синтаксис и могу ли я использовать его, не беспокоясь о проблемах переносимости?

Ответы [ 9 ]

32 голосов
/ 13 октября 2008

Я бы не стал этим пользоваться. Хотя это заманчивое свойство, его синтаксис несовместим с будущим стандартом C ++ 0x, в котором используется:

list<Object> myList;

for (Object o : myList)
{
   o.foo();
}

сделать то же самое.

25 голосов
/ 13 октября 2008

Для каждого не стандартен синтаксис C или C ++. Если вы хотите иметь возможность компилировать этот код в gcc или g ++, вам нужно создать итератор и использовать стандартный цикл for.

QuantumPete

[править] Кажется, это новая функция, введенная в MS Visual C ++, поэтому она определенно не переносима. Ссылка: http://msdn.microsoft.com/en-us/library/xey702bw%28VS.80%29.aspx [/ edit]

21 голосов
/ 13 октября 2008

Существует очень хорошая портативная альтернатива: Boost.Foreach . Просто поместите этот заголовок в свой проект, и вы можете написать свои циклы следующим образом:

list<Object> myList;

BOOST_FOREACH(Object o, myList)
    o.foo();
6 голосов
/ 13 октября 2008

Если вы хотите использовать foreach и в то же время не хотите добавлять дополнительную зависимость (например, Boost) - этот макрос поможет вам:

#define VAR(V,init) __typeof(init) V=(init)
#define FOREACH(I,C) for(VAR(I,(C).begin());I!=(C).end();I++)

std::vector<int> numbers;

FOREACH(I, numbers)
{
    std::cout << *I << std::endl;
}
5 голосов
/ 13 октября 2008

Visual C ++ «для каждого» не является стандартным C ++, то есть вы не сможете скомпилировать свой код на других компиляторах, таких как g ++. Тем не менее, STL предлагает std :: for_each , но его синтаксис гораздо менее интуитивно понятен. Вот его прототип:

template <class InputIterator, class UnaryFunction>
UnaryFunction for_each(InputIterator first, InputIterator last, UnaryFunction f);

Требуется два итератора, определяющих допустимый диапазон, и применяется унарная функция (или функтор) f к каждому объекту в этом диапазоне. Вы можете переписать свой пример, используя std :: for_each, например так:

void foo(Object o)
{
  o.foo();
}
...
list<Object> myList;

std::for_each(myList.begin(), myList.end(), foo);

Однако, если вы хотите оставаться близким к классическому синтаксису для каждой конструкции, и если вы не против использования Boost, вы можете использовать BOOST.FOREACH , что позволит вам написать

list<Object> myList;

BOOST_FOREACH(Object o, myList)
{
    o.foo();
}
2 голосов
/ 13 октября 2008

Библиотека повышения имеет переносимый элемент для ForEach .

1 голос
/ 03 января 2012

Ваш код действительно не переносимый.

Следующее работает со стандартом C ++ 0x и Visual C ++ 2010 (который, насколько я могу судить, не поддерживает новый синтаксис "ranged for").

#define for_each(_ITER_, _COLL_) for (auto _ITER_ = _COLL_.begin(); \
    _ITER_ != _COLL_.end(); _ITER_++)

Теперь вы можете написать:

list<Object> myList;

for_each (o, myList)
{
  o.foo();
}

Сравните это с макрокодом BOOST_FOREACH на http://www.boost.org/doc/libs/1_48_0/boost/foreach.hpp, который не только сложен, но также имеет ряд зависимостей от других библиотек наддува.

0 голосов
/ 13 октября 2008

Я также рекомендую BOOST_FOREACH. Я обычно создаю макрос в соответствии с:

#define _foreach(x,y) BOOST_FOREACH(x,y)

Это повышает читабельность. Вы должны быть осторожны с коллизиями с другими реализациями foreach. Например, Qt предоставляет foreach и есть std :: for_each.

Я считаю, что std :: for_each на самом деле не экономит много времени, так как в итоге вы создаете много одноразовых функциональных объектов для подачи в вызов for_each. Обычно так же быстро создать стандартный цикл for с использованием итераторов STL.

0 голосов
/ 13 октября 2008

Мой голос идет за Люка,

Придерживайтесь стандартных алгоритмов STL, и вам будет намного лучше. Алгоритмы STL могут сделать вашу жизнь очень легкой, эффективной и безопасной. Взгляните на готовые алгоритмы, такие как find_if, count, count_if, sort, transform и т.д ...

Пункт 5 и далее ... http://www.sgi.com/tech/stl/table_of_contents.html

Boost - это круто, но если вы собираетесь использовать его только для макроса FOR_EACH, это слишком громоздко для настройки среды разработки / сборки.

используйте boost, когда стандартный c ++ / stl не может решить проблему «простым» способом.

...