Подтвердить что ты не робот

Visual С++ "для каждой" переносимости

Я только недавно обнаружил, что Visual С++ 2008 (и, возможно, более ранние версии?) поддерживает синтаксис for each в stl lists и др., чтобы упростить итерацию. Например:

list<Object> myList;

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

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

4b9b3361

Ответ 1

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

QuantumPete

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

Ответ 2

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

list<Object> myList;

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

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

Ответ 3

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

list<Object> myList;

BOOST_FOREACH(Object o, myList)
    o.foo();

Ответ 4

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

Visual С++ "для каждого" не является стандартным С++, то есть вы не сможете скомпилировать свой код на других компиляторах, таких как 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();
}

Ответ 7

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

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

#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, который не только сложный, он также имеет ряд зависимостей от других библиотек boost.

Ответ 8

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

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

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

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

Ответ 9

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

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

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

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

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