Я только недавно обнаружил, что Visual C++ 2008 (и, возможно, более ранние версии?) Поддерживает синтаксис for each в списках stl и др., Чтобы облегчить итерацию.
Например:
list<Object> myList;
for each (Object o in myList)
{
o.foo();
}
Я был очень рад обнаружить это, но меня беспокоит переносимость в тот ужасный день, когда кто-то решит, что мне нужно скомпилировать мой код, скажем, в gcc или другом компиляторе. Широко ли поддерживается этот синтаксис, и могу ли я использовать его, не беспокоясь о проблемах переносимости?





Для каждого не используется стандартный синтаксис C или C++. Если вы хотите иметь возможность скомпилировать этот код в gcc или g ++, вам нужно будет создать итератор и использовать стандартный цикл for.
QuantumPete
[редактировать] Кажется, это новая функция, представленная в MS Visual C++, поэтому она определенно не переносима. Ссылка: http://msdn.microsoft.com/en-us/library/xey702bw%28VS.80%29.aspx [/ edit]
В Boost Library есть портативный Для каждой реализации.
Есть очень хорошая портативная альтернатива: Boost.Foreach. Просто загрузите этот заголовок в свой проект, и вы сможете писать свои циклы следующим образом:
list<Object> myList;
BOOST_FOREACH(Object o, myList)
o.foo();
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();
}
Также обратите внимание, что если вы используете VS2010, у вас есть лямбда-выражения, и std :: for_each () внезапно становится легко читаемым.
Я голосую за Люка,
Придерживайтесь стандартных алгоритмов 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 не может решить проблему «простым» способом.
Я также рекомендую BOOST_FOREACH. Обычно я создаю макрос в следующих строках:
#define _foreach(x,y) BOOST_FOREACH(x,y)
Это улучшает читаемость. Однако вы должны быть осторожны с конфликтами с другими реализациями foreach. Например, Qt предоставляет «foreach» и есть std :: for_each.
Я обнаружил, что std :: for_each на самом деле не экономит много времени, поскольку вы в конечном итоге создаете множество одноразовых функциональных объектов для передачи в вызов for_each. Обычно так же быстро можно создать стандартный цикл for с использованием итераторов STL.
В документации Boost.Foreach они явно не рекомендуют писать определение. Вместо этого напишите "#define _foreach BOOST_FOREACH".
Мне нравится оставлять его как BOOST_FOREACH просто потому, что он напоминает, что это расширение макроса, и нужно быть осторожным с тем, что я помещаю в него.
Я бы не стал этим пользоваться. Хотя это заманчивая функция, синтаксис несовместим с грядущим стандартом C++ 0x, в котором используются:
list<Object> myList;
for (Object o : myList)
{
o.foo();
}
сделать то же самое.
Если вы хотите использовать 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;
}
Ваш код действительно не переносится.
Следующее работает со стандартом C++ 0x и Visual C++ 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, который не только сложен, но и имеет ряд зависимостей от других библиотек повышения.
Примечание: для каждого (a в b) кажется, что это CLR только в VS 2005/2008 - вы не можете использовать его в собственном коде, только при нацеливании на .NET, что делает для каждого даже «менее переносимым». В остальном я считаю, что ваш ответ отличный.