Здравствуйте, vdimas, Вы писали:
WH>>Здравствуйте, WolfHound, Вы писали:
WH>>Но при использовании break оптимизатор не смог избавится от оверхеда
V>естественно, потому как логика изменения переменной _fe_break заранее не известна в случае применения break. Если сделать допущение и разделить аргументы типа и переменной, т.е. так: V>
V>foreach(int, i, vec) { ... }
V>
V>то последней конструкцией не будет for (где мы подставляли объявление "int i"), и тогда break и continue работают естественным образом, без оверхеда.
V>вот болванка:
V>
V>int _tmain(int argc, _TCHAR* argv[])
V>{
V> std::vector<int> v;
V> v.push_back(1);
V> v.push_back(2);
V> v.push_back(3);
V> v.push_back(4);
V> int s=0;
V> if(bool _fe_break=false) {} else
V> for(int i;_fe_break==false; _fe_break=true) // тут просто объявили
V> for(const foreach_detail::wrapper_holder
V> &_fe_cur=foreach_detail::wrap(v.begin()),
V> &_fe_end=foreach_detail::wrap(v.end());
V> !foreach_detail::is_wrapped_equal(_fe_cur, _fe_end, v.end());
V> ++foreach_detail::unwrap(_fe_cur, v.end()))
V> if(i=*foreach_detail::unwrap(_fe_cur, v.end()), true) // тут if а не for
V> {
V> if(i==2) break;
V> s+=i;
V> }
V> std::cout <<s;
V> return 0;
V>}
V>
V>break и continue в ассемблерном листинге без оверхеда.
Во-1х вводится лишняя запятая в объявлении макроса, а мы хотим синтаксически приблизится к "нормальному" foreach.
Во-2х такой подход принципиально не прет. Мы хотим иметь возможность объявлять ссылку на элемент последовательности ( FOR_EACH(int& i, vec) ) чтобы изменять эти элементы. А ссылку нельзя переназначить на другой элемент. Значит курсор (не знаю как его правильно обозвать) нельзя отдельно объявлять и отдельно присваивать значение. Объявление курсора не может находиться в if, т.к. неизвестно будет ли тип кусора неявно приводим к bool, а тем более будет ли приводим конкретно к true.
Написал путано, но попробуй сделать чтобы твой подход работал и со ссылками, и все станет ясно. По-моему (и WH видимо также считал) for — единственная подходящая конструкция для объявления курсора.
Здравствуйте, folk, Вы писали:
F>Во-1х вводится лишняя запятая в объявлении макроса, а мы хотим синтаксически приблизится к "нормальному" foreach.
For Each пришел из VB, вообще-то, там это записывалось так:
Dim i as Integer
For Each i in col
' ...Next
т.е. так же можно вынести объявление и в С++:
int i;
foreach(i, vec) s+=i;
F>Во-2х такой подход принципиально не прет. Мы хотим иметь возможность объявлять ссылку на элемент последовательности ( FOR_EACH(int& i, vec) ) чтобы изменять эти элементы.
все ясно, тут не возразишь...
но мне чисто внутренне приятней иметь 3 ассемблерные инструкции для организации цикла, вместо 6-ти (при использовании break)
свой вариант я уже оформил и именно в том виде, как показал выше — с предварительным объявлением.
Ok, беру ваш вариант, и называю его foreach_ref для тех случаев, где потребуется ссылка. (просто у меня чаще всего в коллекциях указатели хранятся, или их браться smart_ptr<они же>, т.е. я про ссылки не учел)
F>Объявление курсора не может находиться в if, т.к. неизвестно будет ли тип кусора неявно приводим к bool, а тем более будет ли приводим конкретно к true.
там у меня не объявление курсора, а присвоение. через запятую у меня там true.
Если бы была допустима такая конструкция:
if((int i=*it), true) {}
но она не допустима
Здравствуйте, vdimas, Вы писали:
V>все ясно, тут не возразишь... V>но мне чисто внутренне приятней иметь 3 ассемблерные инструкции для организации цикла, вместо 6-ти (при использовании break)
Ага, не очень приятно это осозновать, но имхо break используется раз в пятилетку.
V>свой вариант я уже оформил и именно в том виде, как показал выше — с предварительным объявлением. V>Ok, беру ваш вариант, и называю его foreach_ref для тех случаев, где потребуется ссылка. (просто у меня чаще всего в коллекциях указатели хранятся, или их браться smart_ptr<они же>, т.е. я про ссылки не учел)
На всякий случай замечу, что создание копии умного указателя скорее всего обойдется дороже, чем принять его по константной ссылке и (если используется break) потратить вхолостую эти три инструкции.
Здравствуйте, folk, Вы писали:
F>Здравствуйте, vdimas, Вы писали:
V>>все ясно, тут не возразишь... V>>но мне чисто внутренне приятней иметь 3 ассемблерные инструкции для организации цикла, вместо 6-ти (при использовании break)
F>Ага, не очень приятно это осозновать, но имхо break используется раз в пятилетку.
я поражаюсь люди, откуда такие сведения???
я, например, заметил за собой довольной частое использование. откуда статистика?
yxiie:
> F>Ага, не очень приятно это осозновать, но имхо break используется раз в пятилетку. > > я поражаюсь люди, откуда такие сведения??? > я, например, заметил за собой довольной частое использование. откуда статистика?
это была метафора, художественное преувеличение
Сейчас поискал по текущему проекту, нашел 192 looping statement и 77 break, из них 66 находятся внутри switch. Получаем 192/11, т.е. 1 break на 17.(45) циклов.
Понятно что эти цифры ни о чем кроме этого самого проекта не говорят. Просто самому интересно стало.
Здравствуйте, folk, Вы писали:
F>На всякий случай замечу, что создание копии умного указателя скорее всего обойдется дороже, чем принять его по константной ссылке и (если используется break) потратить вхолостую эти три инструкции.
На всякий случай замечу, что пройтись по коллекции с умными указателями всегда удавалось обычным указателем
break я слишком часто юзаю, почти в 1/3 случаев. с ним алгоритмы самые короткие.
vdimas:
> F>На всякий случай замечу, что создание копии умного указателя скорее всего обойдется дороже, чем принять его по константной ссылке и (если используется break) потратить вхолостую эти три инструкции. > > На всякий случай замечу, что пройтись по коллекции с умными указателями всегда удавалось обычным указателем
Зависит от указателей, которые используешь. Бустовые умные не приводимы к "глупому" указателю, надо использовать get(). Так что с ними в FOR_EACH придется создавать копию.
> break я слишком часто юзаю, почти в 1/3 случаев. с ним алгоритмы самые короткие.
Ну что за беда у меня с этими foreach
вариант WolfHound'a время от времени выдает run-time check failure — stack around 'xxx' variable corrupted,
у меня подозрения, что он пропускает больше прогонов цикла, чем нужно, а твой вариант
даже не компилится VC 7.0
f:\...xxx.cpp(24) : error C2667: 'foreach_detail::begin' : none of 2 overloads have a best conversion
f:\Work\prg\unnamed\include\0-utility\lang\foreach.h(281): could be 'foreach_detail::wrapper<boost::range_const_iterator<Range>::type> foreach_detail::begin(const Range &)'
f:\Work\prg\unnamed\include\0-utility\lang\foreach.h(274): or 'foreach_detail::wrapper<boost::range_iterator<Range>::type> foreach_detail::begin(Range &)'
while trying to match the argument list '(const std::list<_Ty,_Ax>)'
with
[
_Ty=Phoenix::PBoundedObject,
_Ax=std::allocator<Phoenix::PBoundedObject>
]
не может выбрать из этих двух вариантов:
template<class Range>
wrapper<typename boost::range_iterator<Range>::type>
begin( Range& range )
{
return boost::begin( range );
}
template<class Range>
wrapper<typename boost::range_const_iterator<Range>::type>
begin(Range const& range )
{
return boost::begin( range );
}
компилировал такое:
const list<PBoundedObject>& objects;
foreach (const PBoundedObject& i, objects)
Кстати я уже делал замечания по поводу этого foreach, но похоже не в этой ветке.
В твоей реализации эта ошибка тоже присутствует:
yxiie wrote:
> Ну что за беда у меня с этими foreach > вариант WolfHound'a время от времени выдает run-time check failure — stack around 'xxx' variable corrupted, > у меня подозрения, что он пропускает больше прогонов цикла, чем нужно, а твой вариант > даже не компилится VC 7.0 > >
> f:\...xxx.cpp(24) : error C2667: 'foreach_detail::begin' : none of 2 overloads have a best conversion
> f:\Work\prg\unnamed\include\0-utility\lang\foreach.h(281): could be 'foreach_detail::wrapper<boost::range_const_iterator<Range>::type> foreach_detail::begin(const Range &)'
> f:\Work\prg\unnamed\include\0-utility\lang\foreach.h(274): or 'foreach_detail::wrapper<boost::range_iterator<Range>::type> foreach_detail::begin(Range &)'
> while trying to match the argument list '(const std::list<_Ty,_Ax>)'
> with
> [
> _Ty=Phoenix::PBoundedObject,
> _Ax=std::allocator<Phoenix::PBoundedObject>
> ]
Ну это явно косяк 7.0, я когда писал ту реализацию и не расчитывал на совместимость с VC6/7.0.
А с вариантом WH надо разобраться — почему там stack corruption. Может оптимизатор чего не так наоптимизировал?
Как вариант лечения FOR_EACHевых проблем могу предложить попробовать BOOST_FOR_EACH от Eric Niebler, он развивается-сопровождается, последняя версия лежит здесь. Может заработает с VC7.0?
> Кстати я уже делал замечания по поводу этого foreach, но похоже не в этой ветке. > В твоей реализации эта ошибка тоже присутствует: > >
> template <class T>
> inline common_ptr<T> BNamespace::Find(const string& name) const {
> BOOST_FOREACH (PEntity i, this->contents)
> // BOOST_FOREACH (const PEntity& i, this->contents) глючит точно также
> if (i->GetName()==name) {
> if (i->GetType()==T::Type)
> return static_pointer_cast<T>(i);
> else
> return NULL;
> }
>
> return NULL;
> }
>
> > я так понимаю это как-то связано с тем, что метод является const.
Здесь http://boost-sandbox.sourceforge.net/libs/foreach/doc/html/boost_foreach/portability.html написано что VC7.0 имеет второй (нижний) уровень совместимости с BOOST_FOREACH, что означает что он не сможет работать с контейнером-rvalue. Но this->contents является const lvalue, так что все должно работать. Напиши в gmane.comp.lib.boost.user о баге, может починят.
> но почему тогда вариант WolfHound нормально компилился?
yxiie:
> КЕ>Здесь http://boost-sandbox.sourceforge.net/libs/foreach/doc/html/boost_foreach/portability.html написано что VC7.0 имеет второй (нижний) уровень совместимости с BOOST_FOREACH, что означает что он не сможет работать с контейнером-rvalue. Но this->contents является const lvalue, так что все должно работать. > > да, я читал... > > КЕ>Напиши в gmane.comp.lib.boost.user о баге, может починят. > > эээ... а как это?
Вот полный урл группы news://news.gmane.org/gmane.comp.lib.boost.user , используешь любой news-клиент, например Outlook Express.
> >> но почему тогда вариант WolfHound нормально компилился? > > КЕ>Тот который с container_traits или без них? > > тот который без. семерка ведь не поддерживает частичную специализацию.
Этот вариант не пытается понять что за контейнер ему передали. Из-за этого ему плевать на константность, но он не может работать ни с чем кроме STL-like контейнеров.
я запостил в boost-users — ошибку компиляции он исправил. но после запуска у его варианта тоже выскаквает stack around variable 'xxx' corrupted. причем даже там, где вариант WolfHound'a работал
Здравствуйте, WolfHound, Вы писали:
WH>1)Оптимизатор в VC++7.1 работает на отлично с ооочень маленьким минусом. WH>2)Учитывая что WH> а)Я уже и не помню когда мне был нужен break/continue WH> б)А цикл с такой смешной нагрузкой я использовал еще раньше... WH>Утверждаю к использованию в своих проектах.
ну и как? используешь ли?
хотелось бы услышать твои впечатления, а то у меня как раз один негатив.
Здравствуйте, yxiie, Вы писали:
Y>ну и как? используешь ли? Y>хотелось бы услышать твои впечатления, а то у меня как раз один негатив.
Было пару раз. Вроде работает. Просто я сейчас на C# пишу... а там практически одни foreach'и...
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, yxiie, Вы писали:
Y>Ну что за беда у меня с этими foreach Y>вариант WolfHound'a время от времени выдает run-time check failure — stack around 'xxx' variable corrupted, Y>у меня подозрения, что он пропускает больше прогонов цикла, чем нужно, а твой вариант
Может дело в Y>даже не компилится VC 7.0
Просто я тлько на 7.1 это пробовал.
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, WolfHound, Вы писали:
WH>Здравствуйте, yxiie, Вы писали:
Y>>ну и как? используешь ли? Y>>хотелось бы услышать твои впечатления, а то у меня как раз один негатив. WH>Было пару раз. Вроде работает. Просто я сейчас на C# пишу... а там практически одни foreach'и...
Здравствуйте, WolfHound, Вы писали:
WH>Здравствуйте, yxiie, Вы писали:
Y>>Ну что за беда у меня с этими foreach Y>>вариант WolfHound'a время от времени выдает run-time check failure — stack around 'xxx' variable corrupted, Y>>у меня подозрения, что он пропускает больше прогонов цикла, чем нужно, а твой вариант WH>Может дело в Y>>даже не компилится VC 7.0 WH>Просто я тлько на 7.1 это пробовал.
черт его знает, а чего в нем особенного такого?
кстати BOOST_FOREACH точно также глючит. даже больше