Здравствуйте, jazzer, Вы писали:
J>Здравствуйте, Аноним, Вы писали:
А>>Здравствуйте, folk, Вы писали:
F>>>#define FOR_EACH_(Decl, First, Last) \ F>>>if (false) {} else /*VC6 for-init-scope bug workaround*/ \
А>>А что это за баг такой и зачем здесь его надо обходить ?
J>баг в том, что в for(int i;); i видна после цикла, а по Стандарту она должна быть видна только внутри цикла
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, jazzer, Вы писали:
J>>Здравствуйте, Аноним, Вы писали:
А>>>Здравствуйте, folk, Вы писали:
F>>>>#define FOR_EACH_(Decl, First, Last) \ F>>>>if (false) {} else /*VC6 for-init-scope bug workaround*/ \
А>>>А что это за баг такой и зачем здесь его надо обходить ?
J>>баг в том, что в for(int i;); i видна после цикла, а по Стандарту она должна быть видна только внутри цикла
А>А в данном случае как это мешает ?
Очень просто — напиши два FOR_EACH подряд, и получишь нарушение ODR по переменной _fe_cur.
F>>Вот создал макрос для перебора всех элементов контейнера, стараясь как можно больше приблизиться к F>>приведенному там синтаксису. F>>В результате организация цикла выглядит примерно так: FOR_EACH(int& i, the_container)
А>А можно ли данный FOR_EACH с std::map использовать ?
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Аноним, Вы писали:
А>>Здравствуйте, folk, Вы писали:
F>>>Навеяно словами WolfHound'a в ветке C++/CLI PDC presentation
F>>>Вот создал макрос для перебора всех элементов контейнера, стараясь как можно больше приблизиться к F>>>приведенному там синтаксису. F>>>В результате организация цикла выглядит примерно так: FOR_EACH(int& i, the_container)
А>>А можно ли данный FOR_EACH с std::map использовать ?
А>Вот так не работает, к сожалению
А>
А>FOR_EACH( pair<string,string>& i, mapStoS )
А>
Здесь у нас одна ошибка и одна проблема.
Ошибка: правильно будет:
FOR_EACH( pair<const string,string>& i, mapStoS )
Проблема: препроцессор понимает запятую между string и string как разделитель аргументов макроса и ругается что макрос FOR_EACH не берет 3 аргумента.
Интересно что я до сих пор не сталкивался с такой проблемой, т.к. всегда пользуюсь value_type. Например:
А>>FOR_EACH( pair<string,string>& i, mapStoS )
А>>
F>Проблема: препроцессор понимает запятую между string и string как разделитель аргументов макроса и ругается что макрос FOR_EACH не берет 3 аргумента. F>Интересно что я до сих пор не сталкивался с такой проблемой, т.к. всегда пользуюсь value_type. Например:
F>
Я считаю, что явно указывать тип переменной в заголовке цикла — лучше т.к. нагляднее демонстрирует по элементам какого типа будем проводить итерации ( контейнер может быть объявлен очень далеко от цикла ).
_>>PS. Жалко что макросы нельзя перегружать — тогда можно было бы не выдумывать новое имя FOR_EACH_M
dad>мне кажется что такой код не только не красивый, но и неправильный..
_>>>PS. Жалко что макросы нельзя перегружать — тогда можно было бы не выдумывать новое имя FOR_EACH_M
dad>>мне кажется что такой код не только не красивый, но и неправильный..
_>В чем неправильность ?
макросы надо рассматривать не как часть языка, а как часть компилятора, имхо,
использование их для сокрытия больших объемов кода, имхо — ламерство,
майкорсов ввело практику карт сообщений, что тоже не есть хорошо, но используется , закрыв глаза.
в этом же случае вообще просматривается попытка использовать макрос как конструкцию языка на подобие функции. что в корне не правильно даже для макроса!
если такая уж нужна — напиши функцию и используй ее зачем макрос то?и потом — такая беда практически не поддается отладке.
Веру-ю-у! В авиацию, в научную революци-ю-у, в механизацию сельского хозяйства, в космос и невесомость! Веру-ю-у! Ибо это объективно-о! (Шукшин)
WolfHound,
Очень клевый foreach, спасибо, вот только у меня VC7.0 спотыкается о:
> //Реализация для массивов > template<class value_t, size_t size_n> > struct container_traits<value_t[size_n]>
пишет:
F:\Work\prg\unnamed\include\0-utility\lang>cl a.cpp
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13.00.9466 for 80x86
Copyright (C) Microsoft Corporation 1984-2001. All rights reserved.
a.cpp
a.cpp(43) : error C2065: 'value_t' : undeclared identifier
a.cpp(43) : error C2065: 'size_n' : undeclared identifier
может я неправильно склеил?
не могли бы Вы привести полный код работающей программы?
без использования обычных массивов компилирует нормально.
Кстати вопрос к тем, кто использовал этот foreach:
за это прошедшее время нашли какие-нибудь ошибки или негативное воздействие
на производительность? Может быть есть какие-то усовершенствования над этим foreach?
Думаю за это время многие уже успели его хорошо обкатать и использовать в деле. Какие отзывы?
Здравствуйте, yxiie, Вы писали:
Y>Очень клевый foreach, спасибо, вот только у меня VC7.0 спотыкается о:
>> //Реализация для массивов >> template<class value_t, size_t size_n> >> struct container_traits<value_t[size_n]>
VC++7.0 не поддерживает частичную специализацию... тут я тебе ни чем помеч не могу. Переходи на VC++7.1 там работает.
... << RSDN@Home 1.1.3 beta 1 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, WolfHound, Вы писали:
WH>Здравствуйте, yxiie, Вы писали:
Y>>Очень клевый foreach, спасибо, вот только у меня VC7.0 спотыкается о:
>>> //Реализация для массивов >>> template<class value_t, size_t size_n> >>> struct container_traits<value_t[size_n]> WH>VC++7.0 не поддерживает частичную специализацию... тут я тебе ни чем помеч не могу. Переходи на VC++7.1 там работает.
А как с частичной специализацией и других компиляторов на других платформах?
Мне нужно, чтобы код был максимально мультиплатформенным.
Кстати, с какой версии _MSC_VER VC++ поддерживает частичную специализацию?
> А как с частичной специализацией и других компиляторов на других платформах?
Все новые версии основных компиляторов C++ на большинстве популярных платформ поддерживают частичную специализацию.
> Кстати, с какой версии _MSC_VER VC++ поддерживает частичную специализацию?
7.1
Posted via RSDN NNTP Server 1.9 alpha
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Lexey, Вы писали:
L>Здравствуйте, WolfHound, Вы писали:
WH>>ЗЫ ИМХО container_traits (ну если еще доработать) самое место в STL. Что скажите?
L>Что-то мне кажется, что в boost.range (1.32) это уже сделали.
Ладно тебе, это было сказано за год до выхода 1.32
А сейчас действительно можно переписать FOR_EACH так, чтобы он использовал boost::begin()/boost::end() и вообще убрать поддержку пары итераторов — вместо них лучше использовать boost::make_iterator_range() или std::make_pair().
Здравствуйте, folk, Вы писали:
F>А сейчас действительно можно переписать FOR_EACH так, чтобы он использовал boost::begin()/boost::end() и вообще убрать поддержку пары итераторов — вместо них лучше использовать boost::make_iterator_range() или std::make_pair().
Переписал. Аргумент макроса Range принимает все, c чем может работать boost::range:
standard-like containers
std::pair<iterator,iterator>
null terminated strings (this includes char[],wchar_t[], char*, and wchar_t*)
built-in arrays
Работа над ошибками.
Было задумано так, что в аргумент Range макроса можно передавать std::make_pair(ptr,ptr). Тут есть проблема — результат make_pair является rvalue, а значит по стандарту не может приниматься функцией по неконстантной ссылке. Предыдущая версия этим не озаботилась, т.к. VC запросто принимает rvalue по неконстантной ссылке.
Исправлено, теперь каждая функция перегружена для константной ссылки.
F>Вот создал макрос для перебора всех элементов контейнера, стараясь как можно больше приблизиться к F>приведенному там синтаксису. F>В результате организация цикла выглядит примерно так: FOR_EACH(int& i, the_container)
F>Несмотря на все это я уже второй день пользую FOR_EACH и FOR_EACH_ и очень доволен.
дело вкуса, я юзаю STL и BOOST мне хватает.
советую глянуть лямбда-вычисления, некая замена безымянных функторов:
if_then(condition, then_part)
if_then_else(condition, then_part, else_part)
if_then_else_return(condition, then_part, else_part)
while_loop(condition, body)
while_loop(condition) // no body case
do_while_loop(condition, body)
do_while_loop(condition) // no body case
for_loop(init, condition, increment, body)
for_loop(init, condition, increment) // no body case
switch_statement(...)
плюс можно биндить функции или функторы
int foo(int);
for_each(v.begin(), v.end(), _1 = bind(foo, _1));
Здравствуйте, Аноним, Вы писали:
А>дело вкуса, я юзаю STL и BOOST мне хватает. А>советую глянуть лямбда-вычисления, некая замена безымянных функторов
[]
std::for_each + boost::lambda, std::for_each + явный функтор, явный цикл, FOR_EACH — можно использовать что угодно, лишь бы было удобно и не было войны.
Здравствуйте, WolfHound, Вы писали:
WH>Но при использовании break оптимизатор не смог избавится от оверхеда
естественно, потому как логика изменения переменной _fe_break заранее не известна в случае применения break. Если сделать допущение и разделить аргументы типа и переменной, т.е. так:
foreach(int, i, vec) { ... }
то последней конструкцией не будет for (где мы подставляли объявление "int i"), и тогда break и continue работают естественным образом, без оверхеда.
вот болванка:
int _tmain(int argc, _TCHAR* argv[])
{
std::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
int s=0;
if(bool _fe_break=false) {} else
for(int i;_fe_break==false; _fe_break=true) // тут просто объявилиfor(const foreach_detail::wrapper_holder
&_fe_cur=foreach_detail::wrap(v.begin()),
&_fe_end=foreach_detail::wrap(v.end());
!foreach_detail::is_wrapped_equal(_fe_cur, _fe_end, v.end());
++foreach_detail::unwrap(_fe_cur, v.end()))
if(i=*foreach_detail::unwrap(_fe_cur, v.end()), true) // тут if а не for
{
if(i==2) break;
s+=i;
}
std::cout <<s;
return 0;
}
break и continue в ассемблерном листинге без оверхеда.