Visual С++ "для каждой" переносимости
Я только недавно обнаружил, что Visual С++ 2008 (и, возможно, более ранние версии?) поддерживает синтаксис for each
в stl lists и др., чтобы упростить итерацию.
Например:
list<Object> myList;
for each (Object o in myList)
{
o.foo();
}
Я был очень рад узнать об этом, но я обеспокоен переносимостью в ужасный день, когда кто-то решает, что мне нужно скомпилировать мой код в say, gcc или какой-то другой компилятор. Является ли этот синтаксис широко поддерживаемым и могу ли я его использовать, не беспокоясь о проблемах с переносимостью?
Ответы
Ответ 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();
}
Ответ 6
В библиотеке Boost имеется переносимая функция EntEach.
Ответ 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 не может решить проблему "простым" способом.