EP>> N>Тут надо было бы пример подправить — reverseFor(i: n..1)
Зачем? Обычно в таких случаях нужны либо индексы, либо просто n итераций — в обоих случаях while(n--) отрабатывает на ура
N>Ну, например, потому что на 1 хоть как-то привычного к такой идиоме будет 10 тех, кто будет смотреть на неё как на новые ворота слишком уж она узкоспецифична.
Запоминается один раз и используются всю жизнь. Повторюсь, встречается повсеместно, рано или поздно всё равно придётся разок посмотреть на эти новые ворота.
Идиома, кстати, применима и к итераторам — у которых может даже и не быть operator<, не говоря уже об one-before-first
Здравствуйте, CreatorCray, Вы писали:
S>>>>#define counter unsigned int; S>>>>for (counter i = 0; i < X; i++) CC>>>
S>>Ох уж эти милые любители фигурных цитат CC>Да там одного define достаточно чтобы зафейспалмить. CC>С "for" просто нагляднее.
Здравствуйте, rg45, Вы писали:
CC>>Нет. Этот for — выпендрёж на ровном месте, R>Кто сказал?
Кто здесь?
R>А я нигде и не настаивал, что записать нужно непременно в одну строчку, неапример: http://rsdn.org/forum/flame.comp/7722412.1
.
И сколько же строчек там занимает сам for ()? Я вижу ровно одну.
R>Ты ж разберись в предмете сначала, потом кидайся.
-1
CC>>за которое давно полагается тапком. R>Воинствующее мракобесие на марше.
С этим — в церковь.
... << RSDN@Home 1.3.110 alpha 5 rev. 62>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Здравствуйте, Evgeny.Panasyuk, Вы писали:
N>>Тут надо было бы пример подправить — reverseFor(i: n..1) EP>Зачем? Обычно в таких случаях нужны либо индексы, либо просто n итераций — в обоих случаях while(n--) отрабатывает на ура
Случай — он разный бывает. Я показываю, на каком варианте итерации "лаконичность" кода с while(n--) исчезает или превращается в недостаток.
N>>Ну, например, потому что на 1 хоть как-то привычного к такой идиоме будет 10 тех, кто будет смотреть на неё как на новые ворота слишком уж она узкоспецифична. EP>Запоминается один раз и используются всю жизнь. Повторюсь, встречается повсеместно, рано или поздно всё равно придётся разок посмотреть на эти новые ворота.
Я лет 20 достаточно плотно пишу на C и читаю сишный код, и такую идиому встречал максимум пару раз, а скорее даже реже.
Мой мир — на 98% обычный юниксовый userland, на пару процентов — ядро (Linux, FreeBSD, OpenBSD) — и я не помню, чтобы там кто-то где-то использовал эти заклинания. Возможно, её применяют в каком-то особом подмирке, типа определённого embedded? Расскажите, где это у вас "встречается повсеместно".
EP>Идиома, кстати, применима и к итераторам — у которых может даже и не быть operator<
От замены в аналоге "i-->1" на "i--!=1" теряется только визуальная красота стрелки.
А именно для итераторов в C++ давно придуманы rbegin и rend, которые, как описано, реализуют хак, который надо отрабатывать явным декрементом. То есть для обратного прохода это превратилось бы в такое:
for (unsigned fi = n; fi >= 1; --fi) { // ну или fi != 0, без разницыunsigned i = fi - 1; // разрезолвляем обратный итератор в прямой :)
bar(i);
}
Кстати, это надо добавить в копилку — спасибо за подсказку. Оно опять же не может обеспечить итерацию для UINT_MAX, но это общая проблема всех таких циклов с предусловием.
GCC перевёл в уже привычный вид:
_Z4foo1j:
test edi, edi
je .L9
push rbx
mov ebx, edi
.L3:
sub ebx, 1
mov edi, ebx
call _Z3barj@PLT
test ebx, ebx
jne .L3
pop rbx
ret
.L9:
rep ret
GCC объединил вообще редакции с fi>=1 и fi!=0 в один код, я не знал, что он такое умеет
Здравствуйте, Marty, Вы писали:
M>Ну вот какой добрый человек тему перенёс? Как мне теперь определить, что я читал, а что — нет?
Определить границу нечитанного можно, к счастью, по плоскому.
Хуже то, что перенос вызвал минимум одного профессионального тролля.
Я там поставил бомбочку перенести обратно.
Здравствуйте, CreatorCray, Вы писали:
CC>Здравствуйте, vopl, Вы писали:
V>>Да, согласен . На один бит. Но не "гораздо меньше". CC>Это ж в два раза
Это ж на 1.15292150461e+18. Квинтиллион километров — это примерный диаметр нашей галактики, которая называется Млечный Путь. Квинтиллион секунд — это время в 2 раза большее, чем то, которое прошло от Большого Взрыва и до сегодняшнего момента. А если мы возьмем квинтиллион молекул чернил, то сможем написать ими какое-нибудь одно, не очень большое, слово. Это не просто "Это ж", это "Это ж" .
Здравствуйте, netch80, Вы писали:
N>>>Тут надо было бы пример подправить — reverseFor(i: n..1) EP>>Зачем? Обычно в таких случаях нужны либо индексы, либо просто n итераций — в обоих случаях while(n--) отрабатывает на ура N>Случай — он разный бывает. Я показываю, на каком варианте итерации "лаконичность" кода с while(n--) исчезает или превращается в недостаток.
А я как бы и не агитирую за это как за самое универсальное и обобщённое решение.
Моя позиция в том, что лучше иметь разные варианты решений в своём инструментарии, особенно если у них есть уникальные плюсы, а не слепо отвергать их из-за каких субъективных предрассудков.
За всякими хаками частенько стоит набор аксиом, концепций, теорем — и то что выглядит на первый взгляд как хак, на самом деле имеет под собой вполне строгую математику
EP>>Запоминается один раз и используются всю жизнь. Повторюсь, встречается повсеместно, рано или поздно всё равно придётся разок посмотреть на эти новые ворота. N>Я лет 20 достаточно плотно пишу на C и читаю сишный код, и такую идиому встречал максимум пару раз, а скорее даже реже. N>Мой мир — на 98% обычный юниксовый userland, на пару процентов — ядро (Linux, FreeBSD, OpenBSD) — и я не помню, чтобы там кто-то где-то использовал эти заклинания. Возможно, её применяют в каком-то особом подмирке, типа определённого embedded? Расскажите, где это у вас "встречается повсеместно".
Ваше благородие, соизвольте заглянуть в ядро Linux следующим grep'ом:
linux-master $ grep -r 'while\s*(\s*[[:alnum:]_]*\s*--\s*).*[^;]' | wc -l
1148
linux-master $ grep -r 'while\s*(\s*[[:alnum:]_]*\s*--\s*).*[^;]' | head -n25
arch/alpha/kernel/io.c: while (count--) {
arch/alpha/kernel/io.c: while (count--) {
arch/alpha/kernel/io.c: while (count--) {
arch/alpha/kernel/io.c: while (count--) {
arch/alpha/kernel/io.c: while (count--) {
arch/arc/include/asm/syscall.h: while (n--) {
arch/arm/mach-davinci/board-dm644x-evm.c: while (ngpio--) {
arch/arm/mach-davinci/board-dm646x-evm.c: while (ngpio--) {
arch/arm/mach-exynos/mcpm-exynos.c: while (tries--) {
arch/arm/mach-orion5x/kurobox_pro-setup.c: while (count--) {
arch/arm/mach-orion5x/terastation_pro2-setup.c: while (count--) {
arch/arm/mach-pxa/pxa3xx-ulpi.c: while (timeout--) {
arch/arm/mach-rpc/ecard.c: while (len--) {
arch/arm/mach-rpc/ecard.c: while (len--) {
arch/arm/mach-rpc/ecard.c: while(len--) {
arch/arm/mach-socfpga/ocram.c: while (limit--) {
arch/arm64/crypto/aes-glue.c: while (blocks--) {
arch/ia64/hp/common/sba_iommu.c: while (cnt--) {
arch/ia64/hp/common/sba_iommu.c: while (cnt--) {
arch/ia64/kernel/cyclone.c: while(stall--) barrier();
arch/ia64/kernel/mca.c: while (slots--) {
arch/ia64/kernel/setup.c: while (max--) {
arch/m68k/amiga/config.c: while (count--) {
arch/m68k/apollo/config.c: while(count--) {
arch/m68k/atari/debug.c: while (count--) {
Ну или в ядро *BSD, что там ближе
EP>>Идиома, кстати, применима и к итераторам — у которых может даже и не быть operator< N>От замены в аналоге "i-->1" на "i--!=1" теряется только визуальная красота стрелки.
А я не об этом. Я о том что вот этот вариант: for (int i=n-1; i>=0; --i) на итераторы не переносится в общем случае, из-за отсутствия отношения порядка и one-before-last. А вариант while(it-- != first) — работает, потому что requires более общие concepts. Вот такой вот "хак".
Точнее one-before-last обходится переносом декремента на первую строчку тела (как уже показывали ранее в этой теме): while(it != first){--it; ...}, но концептуально то же самое.
N>А именно для итераторов в C++ давно придуманы rbegin и rend,
Спасибо кэп, а то ж я не знал.
N>которые, как описано, реализуют хак, который надо отрабатывать явным декрементом.
Хак в base не так паршиво, как хак при разыменовании.
Существует он как раз из-за отсутствия упомянутого мной one-before-first в общем случае. В тех же случаях где мы можем гарантировать валидность итератора one-before-last по построению, этот хак не нужен, и используется более быстрый адаптор без лишних передёргиваний.
N>То есть для обратного прохода это превратилось бы в такое: N>
N>for (unsigned fi = n; fi >= 1; --fi) { // ну или fi != 0, без разницы
N> unsigned i = fi - 1; // разрезолвляем обратный итератор в прямой :)
N> bar(i);
N>}
N>
О том и речь, именно поэтому прямое итерирование вниз может быть предпочительней стандартного reverse_iterator — так как без лишних передёргиваний. Если нужно часто — реализуй в виде ФВП.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>А я как бы и не агитирую за это как за самое универсальное и обобщённое решение. EP>Моя позиция в том, что лучше иметь разные варианты решений в своём инструментарии, особенно если у них есть уникальные плюсы, а не слепо отвергать их из-за каких субъективных предрассудков.
Эти "субъективные предрассудки" превращаются в объективные, когда начинаешь смотреть, как воспринимает такой код не только тот, кто всю жизнь "в системе", как я, а и, например, типовой юниор, часто к тому же перешедший с какого-то соседнего языка.
Увы, есть легко понимаемые приёмы, а есть — с трудом. Вот пост-декремент и пост-инкремент (со взятием значения, а не просто i++ в третьей части заголовка for) это как раз, насколько я вижу по крайней мере по своим коллегам, не очень легко понимаемый вариант.
Поэтому я сразу и начинаю анализировать в эту сторону.
EP>За всякими хаками частенько стоит набор аксиом, концепций, теорем — и то что выглядит на первый взгляд как хак, на самом деле имеет под собой вполне строгую математику
Имеет, да. Но читаешь всё равно шаблонами. И шаблон типа for i in closed_range(n-1, 0, -1) будет читаться проще всегда, чем while(n--).
EP>Ваше благородие, соизвольте заглянуть в ядро Linux следующим grep'ом: grep -r 'while\s*(\s*[:alnum:]_]*\s*--\s*).*[^;]'
Ну я больше имел в виду варианты типа (for(...;i-->0;...). Если это все случаи, то их мало и я на них таки не натыкался. Ядро таки огромное, 1148 это копейки, можно ни разу не встретить. Но учту.
EP>>>Идиома, кстати, применима и к итераторам — у которых может даже и не быть operator< N>>От замены в аналоге "i-->1" на "i--!=1" теряется только визуальная красота стрелки. EP>А я не об этом. Я о том что вот этот вариант: for (int i=n-1; i>=0; --i) на итераторы не переносится в общем случае, из-за отсутствия отношения порядка и one-before-last. А вариант while(it-- != first) — работает, потому что requires более общие concepts. Вот такой вот "хак".
Эээ
вы вообще-то не имеете права декрементировать итератор, равный begin() или rbegin(). Может случиться что угодно.
Или у вас first это не begin? Тогда я не понимаю.
N>>А именно для итераторов в C++ давно придуманы rbegin и rend,
EP>Спасибо кэп, а то ж я не знал.
Иногда очевидности нужны для введения в развитие мысли, как в данном случае. Так что прошу не ёрничать попусту.
(Тем более что вы пытаетесь от begin идти назад — так что, похоже, тут и не кэпство?)
EP>О том и речь, именно поэтому прямое итерирование вниз может быть предпочительней стандартного reverse_iterator — такак как без лишних передёргиваний. Если нужно часто — реализуй в виде ФВП.
Оптимизатор всё равно для типовых случаев вроде плоского массива всё это заоптимизирует.
А через ФВП всё равно получится менее удобно, чем при поддержке foreach самим компилятором.
Здравствуйте, netch80, Вы писали:
EP>>Моя позиция в том, что лучше иметь разные варианты решений в своём инструментарии, особенно если у них есть уникальные плюсы, а не слепо отвергать их из-за каких субъективных предрассудков. N>Эти "субъективные предрассудки" превращаются в объективные, когда начинаешь смотреть, как воспринимает такой код не только тот, кто всю жизнь "в системе", как я, а и, например, типовой юниор, часто к тому же перешедший с какого-то соседнего языка.
Ну давай рассмотрим этот сценарий. Как по-твоему ведёт себя юниор впервые увидевший while(n--)?
EP>>За всякими хаками частенько стоит набор аксиом, концепций, теорем — и то что выглядит на первый взгляд как хак, на самом деле имеет под собой вполне строгую математику N>Имеет, да. Но читаешь всё равно шаблонами. И шаблон типа for i in closed_range(n-1, 0, -1) будет читаться проще всегда, чем while(n--).
Это пока шаблона while(n--) нет в голове.
Да и что означает closed_range в данном случае? запрет на n=0?
EP>>Ваше благородие, соизвольте заглянуть в ядро Linux следующим grep'ом: grep -r 'while\s*(\s*[:alnum:]_]*\s*--\s*).*[^;]' N>Ну я больше имел в виду варианты типа (for(...;i-->0;...). Если это все случаи, то их мало и я на них таки не натыкался. Ядро таки огромное, 1148 это копейки, можно ни разу не встретить. Но учту.
Ну я говорю всё время про while(n--), но можем конечно и вариант с for погрепать. Но суть от этого не меняет — применяется повсеместно.
EP>>>>Идиома, кстати, применима и к итераторам — у которых может даже и не быть operator< N>>>От замены в аналоге "i-->1" на "i--!=1" теряется только визуальная красота стрелки. EP>>А я не об этом. Я о том что вот этот вариант: for (int i=n-1; i>=0; --i) на итераторы не переносится в общем случае, из-за отсутствия отношения порядка и one-before-last. А вариант while(it-- != first) — работает, потому что requires более общие concepts. Вот такой вот "хак". N>Эээ N>вы вообще-то не имеете права декрементировать итератор, равный begin() или rbegin(). Может случиться что угодно.
Да, сам увидел — я это место дополнил:
Точнее one-before-last обходится переносом декремента на первую строчку тела (как уже показывали ранее в этой теме): while(it != first){--it; ...}, но концептуально то же самое.
N>Оптимизатор всё равно для типовых случаев вроде плоского массива всё это заоптимизирует.
Не всегда варианты простые. Тем не менее — прямее сразу делать оптимально по-возможности жеж.
N>А через ФВП всё равно получится менее удобно, чем при поддержке foreach самим компилятором.
Ну это скорее вопрос к синтаксису замыканий и их возможностей. Радикальное отличие for_each+замыкание от range-based-for — только в return/break/continue, остальное синтаксический сахар.