Вот создал макрос для перебора всех элементов контейнера, стараясь как можно больше приблизиться к
приведенному там синтаксису.
В результате организация цикла выглядит примерно так: FOR_EACH(int& i, the_container)
#include <vector>
#include <set>
#include <string>
#include <iostream>
using namespace std;
int main(int argc, const char* argv[])
{
std::set<std::string> str_set;
str_set.insert("red");
str_set.insert("green");
str_set.insert("blue");
FOR_EACH(const string& s, str_set) cout << s << endl;
std::vector<short> short_vec;
short_vec.push_back(-2);
short_vec.push_back(-1);
short_vec.push_back(0);
FOR_EACH(short& i, short_vec) ++i;
FOR_EACH(int i, short_vec)
{
if (i >= 0 && i < argc) cout << argv[i] << endl;
else cout << i << endl;
}
return 0;
}
Вижу в этом решении следующие проблемы (не считая проблем идеологического характера):
1. break работает точно так же, как continue, а хотелось бы полного соответствия семантике цикла.
2. Постоянные ненужные вызовы container.begin() и container.end(), служащие только для определения того, к какому типу надо приводить базовую ссылку. Но проверка asm-листинга VC6 для этого примера показала что все эти вызовы выкидывются оптимизатором. Для VC7.1 даже проверять не стал.
Если бы имелся оператор typeof, то такой проблемы не возникло бы вообще.
3. Ну и конечно же неудобства при отладке такого макроса.
Несмотря на все это я уже второй день пользую FOR_EACH и FOR_EACH_ и очень доволен.
Здравствуйте, Юнусов Булат, Вы писали:
ЮБ>Здравствуйте, folk, Вы писали:
ЮБ>Чем функторы то так не нравятся, рульно же когда цикл в одном месте а алгоритм в другом — нафига обртно все в кучу упихивать то?
Доказывать с пеной у рта не буду, но по-моему не рульно. Потому что расщепляет некую целостность на два фрагмента, далеко расположенных по тексту друг от друга.
Далее. Есть такой принцип : make simple things simple. Или по-русски: не надо для убиения одного комара кидать ядрёную бонбу.
Фактически, единственный профит от for_each, например, то что кишки упрятаны. Типа меньше ошибок и своего рода инкапсуляция получается.
Ну так придумайте инкапсуляцию для операторов как свойство языка. Это было бы, по-моему, куда более продуктивно. Вместо того, чтобы вкладывать колоссальные усилия в реализации на шаблонах. Там нужны усилия и здесь, только в одном случае результатом будет заточка инструмента под решение задач, а во втором -- притягивние задач за уши к инструменту. Т.е. в одном случае продуктивная взаимная любовь, а в другом -- изнасилование.
Поясню немного. Что есть выделенное жирным шрифтом. Оператор цикла, да? После него стоит тело, к которму он применяется.
Фактичкски, здесь стоит inline определение некоторой сущности. Что хочется. Это определение сделать outline. Скрыть детальки, оставив наруже только интерфейс -- входной и операторный. Тогда циклирование сведется к двум шагам: построение этого оператора и применение его к, между прочим, тоже некотрой inline определённой сущности. Ага? Алгоритм же for_each не решает задачи, он просто убирает с глаз долой сам цикл и ничего больше. Не, он ещё создаёт сложности в связывании с телом.
Создаём объект F. Засовываем его через аргумент. Зачем-то. Хотя всё что нужно для дела -- рабочая головка().
F>Вот создал макрос для перебора всех элементов контейнера, стараясь как можно больше приблизиться к F>приведенному там синтаксису. F>В результате организация цикла выглядит примерно так: FOR_EACH(int& i, the_container)
F>Определение макроса:
F>Вот создал макрос для перебора всех элементов контейнера, стараясь как можно больше приблизиться к F>приведенному там синтаксису. F>В результате организация цикла выглядит примерно так: FOR_EACH(int& i, the_container)
F>Определение макроса:
F>
Здравствуйте, Шахтер, Вы писали:
Ш>Доказывать с пеной у рта не буду, но по-моему не рульно. Потому что расщепляет некую целостность на два фрагмента, далеко расположенных по тексту друг от друга.
А нужна она эта целостность? Что лучше отлаживать сам-по-себе одинокий функтор или цикл посреди остального кода?
Ш>Далее. Есть такой принцип : make simple things simple. Или по-русски: не надо для убиения одного комара кидать ядрёную бонбу.
С каких это пор тривиальные вещи стали бомбой? Давай без эмоций и эротических фантазий — они тут неуместы.
Ты во что форич выливается в исходниках видел?
Ш>Фактически, единственный профит от for_each, например, то что кишки упрятаны. Типа меньше ошибок и своего рода инкапсуляция получается.
F>Вот создал макрос для перебора всех элементов контейнера, стараясь как можно больше приблизиться к F>приведенному там синтаксису. F>В результате организация цикла выглядит примерно так: FOR_EACH(int& i, the_container)
хъ
Красота (ну почти см ниже)
F>Вижу в этом решении следующие проблемы (не считая проблем идеологического характера):
Нет ни каких проблем есть фанатизм.
F>1. break работает точно так же, как continue, а хотелось бы полного соответствия семантике цикла.
fixed
F>2. Постоянные ненужные вызовы container.begin() и container.end(), служащие только для определения того, к какому типу надо приводить базовую ссылку. Но проверка asm-листинга VC6 для этого примера показала что все эти вызовы выкидывются оптимизатором. Для VC7.1 даже проверять не стал.
В асм иногода заглядывать надо
В первом варианте в место
std::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(5);
int s=1;
foreach(int& i, v)
{
s*=i;
}
и получалось
cmp edi, esi
push ebp
mov ecx, 1
mov ebp, edi
je SHORT $L10897
push ebx
$L20823:
mov edx, DWORD PTR [ebp]
mov al, 1
$L10901:
; 68 : {
; 69 : s*=i;
mov ebx, edx
imul ecx, ebxtest al, al
sete al
test al, al
jne SHORT $L10901
add ebp, 4
cmp ebp, esi
jne SHORT $L20823
pop ebx
$L10897:
Интересно он сам понял что написал
Хотя может же если мозги не пудрить
cmp edi, esi
mov eax, 1
mov ecx, edi
je SHORT $L10897
$L20663:
; 69 : {
; 70 : s*=i;
mov edx, DWORD PTR [ecx]
add ecx, 4
imul eax, edx
cmp ecx, esi
jne SHORT $L20663
$L10897:
cmp edi, esi
mov ecx, 1
mov eax, edi
je SHORT $L10964
$L20765:
; 76 : {
; 77 : s*=*i;
mov edx, DWORD PTR [eax]
add eax, 4
imul ecx, edx
cmp eax, esi
jne SHORT $L20765
$L10964:
Но при использовании break оптимизатор не смог избавится от оверхеда
int s=1;
foreach(int& i, v)
{
if(i==3)break;
s*=i;
}
s=1;
for(std::vector<int>::iterator i=v.begin(), e=v.end();i!=e;++i)
{
if(*i==3)break;
s*=*i;
}
; 67 : int s=1;
; 68 : foreach(int& i, v)
xor cl, cl
cmp edi, esi
mov edx, edi
je SHORT $L10897
npad 5
$L20665:
cmp cl, bl
jne SHORT $L10897
; 69 : {
; 70 : if(i==3)break;
mov eax, DWORD PTR [edx]
cmp eax, 3
mov cl, 1
je SHORT $L10896
; 71 : s*=i;
imul eax, ebp
mov ebp, eax
xor cl, cl
$L10896:
add edx, 4
cmp edx, esi
jne SHORT $L20665
$L10897:
; 74 :
; 75 : s=1;
; 76 : for(std::vector<int>::iterator i=v.begin(), e=v.end();i!=e;++i)
cmp edi, esi
mov edx, 1
mov ecx, edi
je SHORT $L20822
npad 1
$L20767:
; 77 : {
; 78 : if(*i==3)break;
mov eax, DWORD PTR [ecx]
cmp eax, 3
je SHORT $L20822
; 79 : s*=*i;
imul eax, edx
add ecx, 4
cmp ecx, esi
mov edx, eax
jne SHORT $L20767
$L20822:
Но с continue оверхеда не возникло.
F>Если бы имелся оператор typeof, то такой проблемы не возникло бы вообще.
Ох и не говори... сколько бы он сразу проблем решил... F>3. Ну и конечно же неудобства при отладке такого макроса.
А зачем его отлаживать? Один раз написал и все
F>Несмотря на все это я уже второй день пользую FOR_EACH и FOR_EACH_ и очень доволен.
Итого:
1)Оптимизатор в VC++7.1 работает на отлично с ооочень маленьким минусом.
2)Учитывая что
а)Я уже и не помню когда мне был нужен break/continue
б)А цикл с такой смешной нагрузкой я использовал еще раньше...
Утверждаю к использованию в своих проектах.
... << RSDN@Home 1.1 beta 2 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, WolfHound, Вы писали:
WH>Здравствуйте, alexkro, Вы писали:
A>>А как тебе версия Niebler'а? (ftp://ftp.cuj.com/pub/2003/cujnov2003.zip). WH>И чем он лучше кроме того что там написано больше?
Для массивов работает, например. Да и, вообще, уважаемый человек написал.
Здравствуйте, alexkro, Вы писали:
A>>>А как тебе версия Niebler'а? (ftp://ftp.cuj.com/pub/2003/cujnov2003.zip). WH>>И чем он лучше кроме того что там написано больше? A>Для массивов работает, например.
Ну мой тоже.
А еще чем? A>Да и, вообще, уважаемый человек написал.
Не аргумент.
А вот чем его вариант хуже я могу сказать... Слабо скормить два итератора?
... << RSDN@Home 1.1 beta 2 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, WolfHound, Вы писали:
WH>Здравствуйте, alexkro, Вы писали:
A>>>>А как тебе версия Niebler'а? (ftp://ftp.cuj.com/pub/2003/cujnov2003.zip). WH>>>И чем он лучше кроме того что там написано больше? A>>Для массивов работает, например. WH>Ну мой тоже. WH>А еще чем?
Ok, все беру, и твое решение с break, и стилевые изменения. Только имена макросов все же оставлю заглавными буквами.
Правда я еще не смотрел ссылки от alexkro, сейчас этим и займусь.
А специализации для массивов я не стал создавать потому что у меня на работе используется VC6, соответственно код должен быть VC6-совместимым. Так что для меня лямбда как правило недоступна и утверждение "No more ugly functors (and explicit cycles)" очень актуально.
Здравствуйте, Юнусов Булат, Вы писали:
ЮБ>Впрочем Мейерс лучше сказал http://www.cuj.com/documents/s=8191/cuj0110smeyers/
ЮБ>Кроме того алгоритмы меж собой хорошо сочетаются, вкладываются итп.
ЮБ>Твою задачу тоже можно в функтор посадить, поставить еще бы проверок на все что можно и дальше пользоватся. ЮБ>
Я попрошу не обижаться, но не считаю возможным с вами дискутировать. А то мне придётся нарушить правила форума. Я надеюсь, что вы сами прочтёте свой код ещё раз и поймёте, что не правы.
Что касается господина Мейерса, то статью эту я читал. Мне она не понравилась. Автор явно не профессионал в программировании. Я так понимаю, он алгоритмист.
Смысл этой статьи -- в промоушене своих услуг. Такие вещи надо понимать, это Запад, всё-таки.
P.S.
Знаете, как отличить хорошего программиста от посредственного? По способности не делать мелких ляпов.
Так, профессиональный пианист не ошибается в гаммах, например.
И даю совет напоследок. Если постите код, даже иллюстративный, постарайтесь написать его чисто и аккуратно (и, естественно, правильно).
Не стоит ходить в оперу в заплатанных джинсах -- это неприлично.
[]
A>Классная штука ! A>Не мог бы ты пояснить как работает макрос FOR_EACH_ ? А то не совсем понятно применение врапперов и вложенных циклов.
Сначала про врапперы.
Мы не хотим явно передавать тип контейнера в одном из аргументов макроса, так никакого попса не будет. В то же время для организации цикла нам нужно объявить два итератора — текущий и маркер окончания цикла.
Т.е. проблема в том что без оператора typeof мы никак не можем узнать какой тип итераторов указывать в объявлении.
Решение такое — с помощью функции wrap создаем 2 временных значения — обертки над итераторами и определяем 2 ссылки на базовый класс оберток (их тип известен). Эти обертки будут жить пока живут эти ссылки (thanx 2 jazzer).
Каждый раз когда нам нужно обратиться к итератору мы кастим ссылку на базу к ссыкле на обертку, а от обертки получаем итератор.
Про вложенные циклы.
Первый цикл нужен собственно для организации итерирования по контейнеру.
Второй цикл возвращает управление первому после одной итерации. Он служит только для объявления временного объекта и присвоения ему значения на которое указывает итератор.
Здравствуйте, alexkro, Вы писали:
A>Здравствуйте, WolfHound, Вы писали:
WH>>Здравствуйте, alexkro, Вы писали:
A>>>>>А как тебе версия Niebler'а? (ftp://ftp.cuj.com/pub/2003/cujnov2003.zip). WH>>>>И чем он лучше кроме того что там написано больше? A>>>Для массивов работает, например. WH>>Ну мой тоже. WH>>А еще чем?
A>Если тебе интересно, посмотри здесь: http://aspn.activestate.com/ASPN/Mail/Message/boost/1834496
A>>>Да и, вообще, уважаемый человек написал. WH>>Не аргумент.
A>Для меня аргумент. Я видел больше его кода, чем твоего.
WH>>А вот чем его вариант хуже я могу сказать... Слабо скормить два итератора?
A>using boost::for_each::in_range; A>BOOST_FOREACH( int i, in_range( iter1, iter2 ) ) A>{ A> ... A>}
Если бы он вошел в поставку boost, то вполне возможно стал бы им пользоваться. Но, насколько я понял, этого не будет, несмотря на некоторые положительные отзывы, такое решение не приглянулось ценителям камерного искусства
Здравствуйте, Шахтер, Вы писали:
Ш>Я попрошу не обижаться, но не считаю возможным с вами дискутировать. А то мне придётся нарушить правила форума. Я надеюсь, что вы сами прочтёте свой код ещё раз и поймёте, что не правы.
Беседер, я тоже не горю желаньем, но было бы сначала неплохо узнать где я неправ, если это так, конечно, а хаяние чужого кода никогда никого не красило.
Ш>Что касается господина Мейерса, то статью эту я читал. Мне она не понравилась. Автор явно не профессионал в программировании. Я так понимаю, он алгоритмист. Ш>Смысл этой статьи -- в промоушене своих услуг. Такие вещи надо понимать, это Запад, всё-таки.
Что надо понять? Что Мейерс как бы сказать помягче — популист? Использование stl — это низкопоклонство перез западом? STL Степанов изобрел вообще-то — тоже ради промоушена?
Впрочем, оставим Мейерса, ему не жарко ни холодно от ваших оценок.
Ш>P.S. Ш>Знаете, как отличить хорошего программиста от посредственного? По способности не делать мелких ляпов. Ш>Так, профессиональный пианист не ошибается в гаммах, например. Ш>И даю совет напоследок. Если постите код, даже иллюстративный, постарайтесь написать его чисто и аккуратно (и, естественно, правильно). Ш>Не стоит ходить в оперу в заплатанных джинсах -- это неприлично.
Я не Мейерс, но повертье, меня это тоже не задевает.
Здравствуйте, Шахтер, Вы писали:
Ш> Я попрошу не обижаться, но не считаю возможным с вами дискутировать. Ш> А то мне придётся нарушить правила форума. Я надеюсь, что вы сами Ш> прочтёте свой код ещё раз и поймёте, что не правы. <...> Ш> P.S. Ш> Знаете, как отличить хорошего программиста от посредственного? По Ш> способности не делать мелких ляпов. Так, профессиональный пианист не Ш> ошибается в гаммах, например. И даю совет напоследок. Если постите код, Ш> даже иллюстративный, постарайтесь написать его чисто и аккуратно Ш> (и, естественно, правильно). Не стоит ходить в оперу в заплатанных Ш> джинсах -- это неприлично.
Обязательные правила форумов РСДН http://www.rsdn.ru/rules.htm#IDAQT52B
Не допускается проявление грубого или неуважительного отношения к другим
участникам форума. Оскорблять и обзывать собеседника, ставить под сомнение
его профессиональную квалификацию, придираться к его нику, указывать
на орфографические и синтаксические ошибки и т. д. запрещается.
Настоятельно рекомендую воздерживаться от публикации сообщений, написанных
в таком снисходительно-высокомерном тоне, только на основании того, что ваш
оппонент склонен использовать другие технологии или пишет в стиле, отличном
от того, к которому вы привыкли.
P.S. На всякий случай, добавлю, что отвечать на данное сообщение в форуме
также не следует. Вопросы, пожелания и замечания относительно модерирования
этого и других форумов rsdn.ru — в .
Posted via RSDN NNTP Server 1.7 "Bedlam"
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[6]: No more ugly functors
От:
Аноним
Дата:
08.11.03 13:42
Оценка:
Здравствуйте, Юнусов Булат, Вы писали:
ЮБ> но было бы сначала неплохо узнать где я неправ,