На главную
ПРАВИЛА FAQ Помощь Участники Календарь Избранное DigiMania RSS
msm.ru
Модераторы: ANDLL, ALXR
  
> #define ИЛИ template?, C++
   
#define ИЛИ template
Гости не могут просматривать результаты голосования.
Гости не могут голосовать 
Решил немного оживить раздел голосований. Тематические вопросы. Начнём с одного из популярных


ExpandedWrap disabled
    #define MACROMAX(x,y) \
        ((x < y)?y:x)

ExpandedWrap disabled
    template <typename T1, typename T2>
    T1 templatemax(T1 x, T2 y)
    {
        return (x < y)?y:x;
    }
Сообщение отредактировано: B.V. -
char *out = "|*0>78-,+<|"; size_t cc = char_traits<char>::length(out);
for (size_t i=0;i<cc;i++)??<cout<<static_cast<char>((out??(i??)??'89));??>cout<<endl;


user posted image Чат Исходников в СкайпеЧат Исходников в Дискорде — Не проходим, а заходим!

user posted image
#defnie или const, теоретически вопрос мог бы и так стоять, кстати...
Сообщение отредактировано: Руслан -
нечто нейтральное, пока что.
#define - зло. Если задача решается без него, то всегда предпочту альтернативное решение.

Добавлено
А вообще странная голосовалка и варианты. Нажал "Результаты" :)
Подпись была включена в связи с окончанием срока наказания
#define, как и другие макроопределения - юзается для кроссплатформенного программирования + для гардов компиляции(ну не считая include, без которого никуда, пожалуй единственный полезный макрос, который юзается везде и всегда), ну может быть еще какую вещь упустил. Во всех остальных случаях - за такое нужно бить по рукам, и больно бить.

А то потом люди бедные приходят и задают вопросы, аля - а что я делаю не так, что у меня какой нибудь std::min/std::max не компилируется при включенном windows.h.
Или еще есть любители из макроса целую функцию сделать. Потом такую функцию - продебажить нереально, а порой очень нужно, пусть даже она и работает корректно, и приходится ее переписывать кодом.
Вообще макросы - это тупой мусор, захламляющий код. Я лучше отдам предпочтение юзанью goto, чем использовать макросы в качестве каких нибудь функций. Их использовать нужно тогда и там, где без них либо очень затруднительно что либо сделать, либо совсем нереально.
Например кроссплатформенное программирование.

Добавлено
Вот в том же MFC - иди продебаж карту сообщений. Я дебажил - и это было больно. А нужно было очень, по другому не понятно было где косяк.
Вот из за тех же макросов эту MFC и гнобят все. Да вообще у майкрософта подход к программированию какой то нубско-студенческий. Всюду юзают goto и где не попадя макросы, даже вместо констант. Порой смотришь их MSDN или код какой нибудь функции и диву даешься - неужели там действительно тупарей берут, которые без макросов и goto писать не могут ниче.
Сообщение отредактировано: KILLER -
А где у них в примерах goto?
Подпись была включена в связи с окончанием срока наказания
Цитата OpenGL @
А где у них в примерах goto?

Везде. Начиная от примеров в MSDN и заканчивая API функциями и классами. Странно что ты задаешь такой вопрос. Наверное в MSDN давно не заглядывал или в их код например в том же MFC ?

Добавлено
Например, можешь зайти в C:\Program Files\Microsoft SDKs\Windows\v7.0\Samples, если у тебя SDK стоит, и грепануть по goto(ну или вообще открой любые на свое усмотрения их сырцы и глянь что там).

Добавлено
Ну или еще можно в сырцах MFC/ATL грепануть по goto -> C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\atlmfc

Ну MSDN, на вскидку вот буквально недавно работал с SecurityDescriptor'ами, там вообще кишит этими goto в примерах, например https://msdn.microsoft.com/ru-ru/library/wi...5(v=vs.85).aspx

Добавлено
C #define вместо констант - у меня сложилось такое впечатление, что там это правило, а не исключение из правил.

Вообще эталон говнокода: https://msdn.microsoft.com/en-us/library/wi...9(v=vs.85).aspx

Добавлено
У меня порой складывается впечатление, что в MSDN примеры пишут какие нибудь индусы, которым платят за количество строчек кода.
Сообщение отредактировано: KILLER -
Цитата KILLER @
У меня порой складывается впечатление, что в MSDN примеры пишут какие нибудь индусы, которым платят за количество строчек кода.

дефайны использовались в C, и многим было привычно использовать именно их. Думаю, что это исторически так сложилось и дальше поддкрживается из соображений совместимости.
Тоже самое с goto - Win API не кидают исключения, они возвращают код ошибки. Так было привычно работать в те времена (да блин, даже сейчас коллеги все еще боятся использовать исключения! и стараются вернуть код ошибки хотя пишут уже исключительно на C#). Собственно говоря, именно для обработки ошибок MS и используют goto. Менять поведение нельзя из-за обратной совместимости.
Ну и кроме того, подсчитай, сколько всего #define'ов определено в хидерах MFC, а также всех WinAPI... если заменить каждый дефайн на const int, то это <количество дефайнов> * 4 байта в пустую используемой памяти. И если сейчас всем глубоко наплевать на это, то в 1985 (именно тогда появился Windows 1.0)... ну ладно, даже в 1995-ом году, когда Винда стала самостоятельной операционной системой, к расходу памяти относились очень осторожно. Ну а дальше уже нельзя было менять дефайны на константы ради обратной совместимости. Более того, ради того, чтобы код был в едином стиле приходится и дальше следовать утвержденным когда-то давно правилам.

Так что причины, почему MFC и WinAPI написаны именно так очевидны.
- Завтра или послезавтра придет фруктовый пароход из Мобила, - сказал Джонни. - А до той поры нам делать нечего.
- Но что вы намерены делать? Создать спрос?
- Много вы понимаете в политической экономии, - ответил консул довольно невежливо. - Спроса создать нельзя. Но можно создать условия, которые вызовут спрос.
Цитата Fester @
если заменить каждый дефайн на const int, то это <количество дефайнов> * 4 байта в пустую используемой памяти.

Константы не используют память. Точнее, память под них будет выделена только если ты начнёшь брать указатели на эти константы и что-то с ними делать, а в 99.9% случаев это нафиг не надо.
Подпись была включена в связи с окончанием срока наказания
Цитата Fester @
дефайны использовались в C

И что у них была какая то другая цель, отличная от С++? Они что в C были макросами, что в С++ стали макросами. В С есть константы, на сколько я помню, так что такое оправдание не катит.

Цитата Fester @
Думаю, что это исторически так сложилось и дальше поддкрживается из соображений совместимости.

Как сложилось? Не было типов данных, констант и переменных? Писали все в макросах? Или что?

Цитата Fester @
Тоже самое с goto - Win API не кидают исключения, они возвращают код ошибки. Так было привычно работать в те времена (да блин, даже сейчас коллеги все еще боятся использовать исключения! и стараются вернуть код ошибки хотя пишут уже исключительно на C#). Собственно говоря, именно для обработки ошибок MS и используют goto.

Ты знаешь, я сколько писал на чистом С, как то не приходилось использовать goto. С goto хоть С, хоть в С++, хоть в C# - везде хреново, и без него великолепно все возвращается и очищается. Просто кто то ленится и пишет goto где не попадя.

Цитата Fester @
Менять поведение нельзя из-за обратной совместимости.

Из за какой совместимости то? Не совсем тебя понял.

Цитата Fester @
Ну и кроме того, подсчитай, сколько всего #define'ов определено в хидерах MFC, а также всех WinAPI... если заменить каждый дефайн на const int, то это <количество дефайнов> * 4 байта в пустую используемой памяти. И если сейчас всем глубоко наплевать на это, то в 1985 (именно тогда появился Windows 1.0)... ну ладно, даже в 1995-ом году, когда Винда стала самостоятельной операционной системой, к расходу памяти относились очень осторожно. Ну а дальше уже нельзя было менять дефайны на константы ради обратной совместимости. Более того, ради того, чтобы код был в едином стиле приходится и дальше следовать утвержденным когда-то давно правилам.

Так а причем тут дефайны в хидерах, где например они объявляют битовые маски ? Речь про дефайны зашла в примерах конкретно, и в тех местах - где они ломают стандартные функции. У них часть дефайнов конкретно в библиотеках - написаны как раз в тему. А часть - не в тему. Хорошо - пусть они там экономили на константах, но объясни мне, зачем функции/методы/и целые классы оборачивать в дефайны? Тоже для экономии места или как?

Цитата Fester @
Ну а дальше уже нельзя было менять дефайны на константы ради обратной совместимости. Более того, ради того, чтобы код был в едином стиле приходится и дальше следовать утвержденным когда-то давно правилам.

Да да да конечно. Почему это нельзя? Ты только один пример из MSDN увидел? Там как раз есть примеры годные, не говнокодные, без всяких goto и дефайнов, а часть примеров - сплошной говнокод, как по оформлению, так и по применению конструкций языка.

Цитата Fester @
Так что причины, почему MFC и WinAPI написаны именно так очевидны.

Мне нисколько не очевидны.

Добавлено
Цитата OpenGL @
Константы не используют память. Точнее, память под них будет выделена только если ты начнёшь брать указатели на эти константы и что-то с ними делать, а в 99.9% случаев это нафиг не надо.

Тогда темболее, объяснение Fester про память было не совсем в тему.

Добавлено
Цитата Fester @
да блин, даже сейчас коллеги все еще боятся использовать исключения! и стараются вернуть код ошибки хотя пишут уже исключительно на C#

А чего бояться? Боятся что исключение их укусит? Или они просто матерые сишники, которые по привычке в придачу пишут все в одном классе, не используют наследование, и все методы у них статические, и то! Только из за того, что в C# нельзя написать функцию вне класса? Может им на пенсию пора? :D
Цитата OpenGL @
Константы не используют память.

Это всегда так было или только в некоторых компиляторах? Я так понимаю, что это оптимизация компилятора... или как?


Цитата KILLER @
И что у них была какая то другая цель, отличная от С++? Они что в C были макросами, что в С++ стали макросами. В С есть константы, на сколько я помню, так что такое оправдание не катит.

Я не могу расписать тебе в чем именно в те лохматые годы отличались константы от дефайнов. Но я все таки исхожу из того, что программисты были не глупее тебя и точно знали что и почему они делали. По каким-то причинам были выбраны именно макросы. Если ты хочешь доказать, что программисты в MS в середине 80-х были дебилы - доказывай.


Цитата KILLER @
Ты знаешь, я сколько писал на чистом С, как то не приходилось использовать goto. С goto хоть С, хоть в С++, хоть в C# - везде хреново, и без него великолепно все возвращается и очищается.

Конечно. Все можно обойти ифами. C этим никто не спорит. В некоторых случаях goto заметно упрощает код. Собственно говоря, ты используешь finally в своем коде? А ведь по сути это тот же goto ;) Избегать goto исключительно ради избегания - это не самая хорошая тактика. И если использование goto упрощает понимаение кода, то я лично не вижу ничего плохого в его использовании.

Цитата KILLER @
Из за какой совместимости то? Не совсем тебя понял.

Обратной. Чтобы ты мог в старом коде использовать новые библиотеки.
Грубо говоря, если у тебя есть функция
ExpandedWrap disabled
    int Div (int a, int b)
    {
      if (a < b)
        return NOT_POSSIBLE;
      if (b == 0)
        return DIVISIO_BY_ZERO;
      return a / b;
    }


то если ты перепишешь так:
ExpandedWrap disabled
    int Div (int a, int b)
    {
      if (a < b)
        throw "a must be >= b";
      if (b == 0)
        throw "division by zero";
     
      return a / b;
    }


то тебе придется переписать уже существующий код.

Добавлено
Цитата KILLER @
А чего бояться? Боятся что исключение их укусит?

Боятся, что исключение не будет обработано и это приведет к крэшу :)
У нас один такой бояка везде вставляет
ExpandedWrap disabled
    ...
    catch (...)
    {
      Log.Error ("any exception");
    }

после такого очень забавно вылавливать баги :)
- Завтра или послезавтра придет фруктовый пароход из Мобила, - сказал Джонни. - А до той поры нам делать нечего.
- Но что вы намерены делать? Создать спрос?
- Много вы понимаете в политической экономии, - ответил консул довольно невежливо. - Спроса создать нельзя. Но можно создать условия, которые вызовут спрос.
Цитата Fester @
Это всегда так было или только в некоторых компиляторах? Я так понимаю, что это оптимизация компилятора... или как?
Не всегда. Не оптимизация, новое требование Стандарта... запамятовал, какой именно версии. И что там на предмет C, без понятия, и в стандарты лезть лень. Не исключено, что по-прежнему const int и К° являются lvalue даже со static, и нии... в смысле, пофигу.
Обработка ошибок посредством __leave в примерах MSDN появилась только с появлением этого самого __leave в компиляторе. Обработка ошибок посредством SEH в примерах MSDN сильно усложняет перенос кода на другие языки. Говнокод в лице примеров в MSDN является просто крайне разжёванной реализацией иллюстрируемой идеи, опять-таки для пользователей других языков. Только тут ещё и другой нюанс: эти примеры учат, и как учебные примеры они и должны быть разжёваны

Добавлено
И вообще. Вы совсем не те #define обсуждаете.
Одни с годами умнеют, другие становятся старше.
Цитата Fester @
Если ты хочешь доказать, что программисты в MS в середине 80-х были дебилы - доказывай.

А что доказывать? В 80-х думаю что не то что бы MSDN'а, Даже тех функций которые сейчас там описаны не было, ну может за исключением каких то объектов ядра или еще чего то.

Цитата Fester @
Собственно говоря, ты используешь finally в своем коде?

Нет. Я на С/С++ в основном программирую. А если следовать твоей логике - любой return/break/continue/и т.п. по сути тот же goto. Только return - не нарушает структуры выполнения программы, а goto нарушает. Именно по этому его всегда и гнобили.

Цитата Fester @
Избегать goto исключительно ради избегания - это не самая хорошая тактика. И если использование goto упрощает понимаение кода, то я лично не вижу ничего плохого в его использовании.

Возможно в каких то там исключительных случаях - когда тебе нужно выйти из 4-ого по вложенности цикла - оно и упрощает понимание кода, но в тех примерах где они его используют, там и без goto обойтись не составляет проблем, без нарушения структуры исполнения программы.

Цитата Fester @
Обратной. Чтобы ты мог в старом коде использовать новые библиотеки.

Обратная совместимость нарушается тогда, когда ты меняешь например сигнатуру метода/функции/класса и т.д.
Например была у тебя функция bool OpenFile(file_name, desired_acces, dos_format);
Потом вышла новая версия венды, и последний параметр стал вообще нафиг никому не нужен, так вот если его уберут - то сломают обратную совместимость, и по этому делают либо вторую функцию, либо оставляют прежнюю, но делают оговорку в документации - что третий параметр зарезервирован и должен быть равен NULL(например).

А когда ты рефакторишь что то внутри функции, не меняя ее сигнатуру - как ты можешь поломать обратную совместимость? Ты может не goto имел ввиду или перепутал что то с чем то?

Цитата Fester @
то тебе придется переписать уже существующий код.

В данном случае не обязательно. По крайней мере до возникновения ошибки ничего не случится. И ты немного съехал с темы. Речь шла про goto, а не про коды возврата/исключения. Если я внутри функции избавлюсь от goto - ничего я не поломаю. Так что это пока не аргумент.

Цитата Fester @
Боятся, что исключение не будет обработано и это приведет к крэшу :)

А это что плохо? Если у тебя произошло исключение - это значит код, который его кинул - не смог справится с ошибкой. Коды возврата тебе тут не помогут. Если ты боишься что где то не обработаешь исключение, то почему ты не боишься того, что где то ты не проверишь возвращаемое значение? И все равно это приведет к крэшу, и хорошо - если к крэшу, так хоть упало - и сразу все понятно. А если будет не крэшь а произойдет операция - которая в принципе не должна произойти? По моему это хуже крэша.

Цитата Fester @
У нас один такой бояка везде вставляет

С кодами возврата можно отгребсти куда больше проблем. И таких ошибок, что catch(...) тебе сказкой покажется. Там хоть бряк можно поставить, и сразу туда вылететь в этот catch.
Так что это слабенький аргумент.
Цитата KILLER @
Обратная совместимость нарушается тогда, когда ты меняешь например сигнатуру метода/функции/класса и т.д.

Не только. Обратная совместимость нарушается, когда меняется поведение класса.
Например как в моем примере - был возврат ошибки, стало исключение. Если не поменять старый код, то в случае ошибки завалится вся программа.
Обратная совместимость также может поменяться если ты просто переименуешь или добавишь еще одно одно исключение. ДА мало ли примеров, когда можно нарушить обратную совместимость не изменяя сигнатуру?
Другой момент, что изменив сигнатуру ты спровоцируешь ошибки и другой разработчик сразу узнает, что что-то поменялось.


Цитата KILLER @
По моему это хуже крэша.

Крэш - это полный отказ, в то время как какая-то незавершенная или неправильная операция совсем не означает, что приложение больше неработоспособно.
Например наш софт сбирает данные и пишет их в БД. Плохо конечно, если какие-то данные не запишутся, но не смертельно, а если прога крэшнится, то не запишится вообще ничего и никто не знает, когда это заметят.
Поэтому крэш - это очень плохо.

Цитата KILLER @
Коды возврата тебе тут не помогут. Если ты боишься что где то не обработаешь исключение, то почему ты не боишься того, что где то ты не проверишь возвращаемое значение?

потому что исключение может прилететь откуда угодно, а все возвращаемые значения заранее известны.
- Завтра или послезавтра придет фруктовый пароход из Мобила, - сказал Джонни. - А до той поры нам делать нечего.
- Но что вы намерены делать? Создать спрос?
- Много вы понимаете в политической экономии, - ответил консул довольно невежливо. - Спроса создать нельзя. Но можно создать условия, которые вызовут спрос.
Цитата Fester @
Обратная совместимость нарушается, когда меняется поведение класса.

Я же тебе написал - что ты немного не в ту сторону съехал. Причем тут поведение классов меняется? Мы не обсуждали return/throw. Ты написал:
Цитата Fester @
Собственно говоря, именно для обработки ошибок MS и используют goto. Менять поведение нельзя из-за обратной совместимости.

Цитата Fester @
Ну а дальше уже нельзя было менять дефайны на константы ради обратной совместимости.


В данном случае обратная совместимость не ломается. Потому что, если ты избавляешься от goto(не меняешь поведение, поведение можно и с goto поменять), а именно стоит задача избавиться от goto.
Ну и с дефайнами и константами не совсем понял, как там ломается обратная совместимость?

Цитата Fester @
Обратная совместимость также может поменяться если ты просто переименуешь или добавишь еще одно одно исключение.

Зачем ты это пишешь? Ведь это не имеет никакого отношения к обсуждаемой теме. Еще обратная совместимость ломается когда ты меняешь типы данных, меняешь логику, меняешь сигнатуру, и т.д. Но как это относится к макросам и goto, я в упор не понимаю? Это попытка уйти от прямого вопроса? Я у тебя спросил - как ты поломаешь обратную совместимость, просто избавившись от goto, ты приводишь мне пример с return/throw и приводишь мне какие то случаи когда она еще может ломаться. Да я и так знаю когда она ломается, а когда нет. А вот ты похоже не до конца понимаешь. Иначе ответил бы на мой вопрос, а не лил воду про то, что я у тебя не спрашивал.

Цитата Fester @
ДА мало ли примеров, когда можно нарушить обратную совместимость не изменяя сигнатуру?

https://ru.wikipedia.org/wiki/%D0%9E%D0%B1%...%81%D1%82%D1%8C
Цитата
Обра́тная совмести́мость — наличие в новой версии компьютерной программы или компьютерного оборудования интерфейса, присутствующего в старой версии, в результате чего другие программы (или человек) могут продолжать работать с новой версией без значительной переделки (или переучивания). Полная обратная совместимость означает, что при замене старой версии компонента на новую, функционирование всей системы в целом не нарушится.


Цитата Fester @
Другой момент, что изменив сигнатуру ты спровоцируешь ошибки и другой разработчик сразу узнает, что что-то поменялось.

Именно эти ошибки и есть - сломанная обратная совместимость. Если ты избавился от goto внутри функции - ничего ты не сломаешь.

Цитата Fester @
Крэш - это полный отказ, в то время как какая-то незавершенная или неправильная операция совсем не означает, что приложение больше неработоспособно.

А зачем нужно приложение, которое работает не верно? Вообще то по хорошему - лучше упасть, чем работать неверно. Лучше уж прямой крешь, чем неверная работа приложения, которая может привести к невесть чему, включая искажение или полную потерю информации или еще чего.

Цитата Fester @
Например наш софт сбирает данные и пишет их в БД. Плохо конечно, если какие-то данные не запишутся, но не смертельно, а если прога крэшнится, то не запишится вообще ничего и никто не знает, когда это заметят.
Поэтому крэш - это очень плохо.

Вообще то лучше пусть они вообще не сохранятся, чем сохранятся неверные данные. Если ты 8 часов сидел забивал данные в базу без комита, а потом к концу 8-ого часа у тебя все упало, то ты сам виноват. Тебе никто не запрещал сохранять данные. А вот если ты пишешь одно, а созхраняет в базу совершенно другое - то это в 100 раз хуже. ИМХО.

Цитата Fester @
Поэтому крэш - это очень плохо.

Это плохо, но не смертельно. А вот когда у тебя программа работает с некорректными данными, а ты еще об этом даже не догадываешься - вот тут будет полнейшая жопа. Ты просто можешь реально влететь в такую жопу. Что потом забудешь return, и будешь вместо него везде писать throw.

Цитата Fester @
потому что исключение может прилететь откуда угодно, а все возвращаемые значения заранее известны.

Блин, я не понимаю как вы программируете? Ты юзаешь функцию и незнаешь - кидает она тебе исключение или нет? или что? Да откуда бы оно не прилетело - ты можешь открыть дамп и посмотреть стек, и сразу понять - что и в каком месте у тебя вылетело. А в вашем C#, так вообще не нужно никуда лезть и смотреть, дефолтный обработчик, даже если ты там ниче не ловил и так тебе покажет какую никакую информацию в окошке и в журнале событий.
А вот когда твое приложение дебет с кредетом не сведет, и бедный предприниматель уволит всех своих сотрудников, вот тогда ты точно поймешь - как ты ошибался.
Цитата KILLER @
... а именно стоит задача избавиться от goto.
Зачем? Во-первых, это известный legacy C паттерн, пол-POSIX-а так писано, к слову. Во-вторых, это тот же finally, только руками.
Одни с годами умнеют, другие становятся старше.
Очередной срачик на тему "коды возврата vs исключения"? :)
Вообще, согласен с KILLER-ом - бояться забыть перехватить исключение и не бояться забыть проверить код возврата это прямо-таки образец двойных стандартов. Имхо, коды возврата можно предпочитать исключениям только при наличии в языке мощной системы типов, позволяющей писать обёртки вроде Either/Option, с которыми сам компилятор будет проверять, все ли возможные варианты возвращаемого значения ты рассмотрел. В языках же типа С/С++, а тем более C# они больше добавляют проблем, чем решают.
Подпись была включена в связи с окончанием срока наказания
Цитата Qraizer @
Зачем? Во-первых, это известный legacy C паттерн, пол-POSIX-а так писано, к слову. Во-вторых, это тот же finally, только руками.

Затем что об этом пошла речь. Можно писать и полный говнокод, а на вопрос - может отрефакторим - отвечать "зачем? Во первых, это известный legacy C паттерн, пол-POSIX-а так написано.".
Цитата KILLER @
Потому что, если ты избавляешься от goto(не меняешь поведение, поведение можно и с goto поменять), а именно стоит задача избавиться от goto.

Избавиться от goto (я говорю о возврате ошибок) можно двумя способами:
1) нагородить кучу if'ов. Очевидно, что это усложнит код.
2) кидать исключения вместо того, чтобы возвращать код ошибки. Это решение уничтожит обратную совместимость.

Еще раз, само по себе использование goto - не есть зло. Нужно только, чтобы это использование было оправдано и чтобы goto упрощал понимание кода.


Цитата KILLER @
А зачем нужно приложение, которое работает не верно? Вообще то по хорошему - лучше упасть, чем работать неверно.

Неверное оно может работать например из-за того, что неверно отработала какая-то железка. Например не пришли все данные и ты в результате не момежешь сохранить блок данных в БД, но при этом надо уже обрабатывать следующий блок данных.
Вообще, ошибки бывают разные и возникновение ошибок не означает, что программа работает неверно ;)


Цитата KILLER @
Блин, я не понимаю как вы программируете? Ты юзаешь функцию и незнаешь - кидает она тебе исключение или нет?

В общем случае ты не можешь гарантировать, что в документации перечислены все кидаемые исключения.

Ну и у нас микс - С++ и C# :ph34r:
- Завтра или послезавтра придет фруктовый пароход из Мобила, - сказал Джонни. - А до той поры нам делать нечего.
- Но что вы намерены делать? Создать спрос?
- Много вы понимаете в политической экономии, - ответил консул довольно невежливо. - Спроса создать нельзя. Но можно создать условия, которые вызовут спрос.
Цитата Qraizer @
Зачем? Во-первых, это известный legacy C паттерн, пол-POSIX-а так писано, к слову. Во-вторых, это тот же finally, только руками.

Да, и к слову - чем хуже do/while + break ? По моему скромному мнению - это известный legacy C паттерн, который в 100 раз читабельней и структурированее, чем эти всякие goto.

Добавлено
Цитата Fester @
1) нагородить кучу if'ов. Очевидно, что это усложнит код.
2) кидать исключения вместо того, чтобы возвращать код ошибки. Это решение уничтожит обратную совместимость.

3)
ExpandedWrap disabled
    do
    {
        /*... Something...*/
       RetVal = GetLastError();
       if(RetVal != ERROR_SUCCESS)
          break;
        
        /*Do something*/
       ....
    }while(false);
     
    //! Clean Up


используя goto - от кучи if'ов - ты никуда не денешься. Посмотри хотя бы как используют goto на том же MSDN

Добавлено
Цитата Fester @
Еще раз, само по себе использование goto - не есть зло.

именно что самое по себе использование goto - зло. Потому как ты можешь прыгать по подпрограмме - взад-вперед, а это нарушает стуктурированность приложения, и куда ты там прыгнешь - предугадать в некоторых случаях без отладки нереально.

Цитата Fester @
Неверное оно может работать например из-за того, что неверно отработала какая-то железка.

Да вот в твоем примере про деление, тебе возратило код возврата Деление на ноль, а ты не проверил код возврата, и записываешь результат в базу, причем не корректный результат. И к чему это потом приведет?

Цитата Fester @
В общем случае ты не можешь гарантировать, что в документации перечислены все кидаемые исключения.

Тогда это уже не мои проблемы темболее. Ты тоже не можешь гарантировать что в документации перечислены все коды возврата.

Цитата Fester @
Ну и у нас микс - С++ и C# :ph34r:

И что? Обычное дело через С++/cli. Какие проблемы?
Странный опрос :)
Можно показать примеры кода? В каком контексте сравниваем-то?
"If someone claims to have the perfect programming language, he is either a fool or a salesman or both"(c) Bjarne Stroustrup
Цитата KILLER @
3)

Это - типичный паттерн, пишущийся ради религиозной заморочки "лишь бы не было goto". Если пишешь на С, то goto cleanup по мне так удобней и читаемей, чем такой вот do{}while(false); В плюсах да, такое нафиг не надо.
Подпись была включена в связи с окончанием срока наказания
Цитата KILLER @
Да, и к слову - чем хуже do/while + break ? По моему скромному мнению - это известный legacy C паттерн, который в 100 раз читабельней и структурированее, чем эти всякие goto.

Ничем этот паттерн не лучше goto которого ты так боишься, ни в плане читаемости, ни тем более в плане работы/быстродействия.

ExpandedWrap disabled
      mem=malloc(size);
      // ...
      for(i=0; i<100; i++)
      {
        for(j=0; j<100; j++)
        {
          if(some_data[i][j]==SOME_VALUE) goto exit;
          mem[i*100+j]=some_data[i][j];
        }
      }
     
    exit:
      free(mem);
      return 0;


Напиши то же самое с do/while, for, break, continue и т.п. и без дублирования кода.

Можно конечно написать
ExpandedWrap disabled
    if(some_data[i][j]==SOME_VALUE)
    {
      i=100;
      break;
    }

или дублировать весь код очистки + return - но это ни разу не лучше будет читаться.
Сообщение отредактировано: cppasm -
Цитата cppasm @
Ничем этот паттерн не лучше goto которого ты так боишься, ни в плане читаемости, ни тем более в плане работы/быстродействия.

Этот пример абсолютно не в тему. Вот вообще. Потому как я о нем писал выше.

Цитата OpenGL @
Это - типичный паттерн, пишущийся ради религиозной заморочки "лишь бы не было goto". Если пишешь на С, то goto cleanup по мне так удобней и читаемей, чем такой вот do{}while(false); В плюсах да, такое нафиг не надо.

Нет, ты видимо все таки не смотрел Microsoft SDK, где goto вхерачен в макрос, который представляет из себя часть какой то то ли функции, то ли проверки, и потом таким же макросом расставлены метки?
Это пичально. Этот пример лишь показывает как легко и не принужденно эмулировать goto, без потери читабельности. Будет у тебя 1 метка, и 1 переход - с этим можно жить. Но ты ведь не ходил по ссылкам, не смотрел код миркософта. И рассуждаешь об абстрактных конях в вакууме.
Избавится от goto - это нужно правильно проектировать архитектуру. А goto - для лентяев, и является очень частым источником ошибок, и заморочек. Либо ты только с академической стороны встречал goto в синтетических примерах, по этому так и рассуждаешь, либо рассматриваешь конкретный случай. Будет у тебя 2 метки, и два разных goto - ты уже сходу не врубишься в написанное. А я как то пытался рефакторить код, где на С понахерячили всю логику на goto вот такие же философы, которые не видят ничего плохого в goto. Встретил бы автора - оторвал бы руки. Потому как код я рефакторить не стал, я его просто удалил и написал все заного, без всяких goto, понятно и прозрачно.

Цитата cppasm @
Напиши то же самое с do/while, for, break, continue и т.п. и без дублирования кода.

Напишу. Но не сейчас. Я сейчас занят. Но идея такова - избавится от вложенного цикла. Твой код синтетический и надуманный. Ты хочешь сказать его не реально по другому переписать никак? Я если что в него даже не в никал, просто по диагонале посмотрел не особо вдумываясь в смысл написанного.
Сообщение отредактировано: KILLER -
Цитата KILLER @
Этот пример абсолютно не в тему. Вот вообще. Потому как я о нем писал выше.

Чем он не в тему?
Ты же писал что
Цитата KILLER @
именно что самое по себе использование goto - зло.



Цитата KILLER @
Нет, ты видимо все таки не смотрел Microsoft SDK, где goto вхерачен в макрос, который представляет из себя часть какой то то ли функции, то ли проверки, и потом таким же макросом расставлены метки?
Это пичально.

Это печально что ты не приводишь конкретных примеров, а только бла бла бла...
По ссылкам твоим ходил - нигде там такого нету.
В основном везде переход на Cleanup из середины функции.


Цитата KILLER @
Но идея такова - избавится от вложенного цикла. Твой код синтетический и надуманный.

Во-первых код не надуманный, а упрощённый.
Никогда при написании кода не возникало необходимости вывалиться из нескольких вложенных циклов?
Во-вторых идея избавиться от вложенных циклов только потому что тебе goto не нравится фиговая, т.к. в реальных условиях от вложенных циклов избавиться получится далеко не всегда.
Цитата KILLER @
Можно писать и полный говнокод, а на вопрос - может отрефакторим - отвечать "зачем? Во первых, это известный legacy C паттерн, пол-POSIX-а так написано.".
Можно и говнокод писать. Но лучше не надо. А патерн, как бы тебе лично не хотелось, он патерн. Его знают, узнают с пол-взгляда и сразу понимают, что он делает и зачем вообще нужен. Ну, те, кто о нём знает, конечно. Я вот из декоратора знаю только название, и уже не помню, зачем он собственно нужен, так что запросто, увидев в твоём коде и не распознав, заору "говнокод". Буду ли я прав?.. зависит от обстоятельств, не так ли? Твои апелляции к примерам MSDN – это не те обстоятельства, когда говнокод, и я объяснил, почему.

Добавлено
Цитата KILLER @
Да, и к слову - чем хуже do/while + break ? По моему скромному мнению - это известный legacy C паттерн, который в 100 раз читабельней и структурированее, чем эти всякие goto.
По меньшей мере тем, что это не патерн обработки ошибок. А ещё тем, что обработка ошибок зачастую ломает структурность алгоритма. Напрочь. Попытки обернуть неструктурность алгоритма в фантик структурности наивны, т.к. наносят вред.
Сообщение отредактировано: Qraizer -
Одни с годами умнеют, другие становятся старше.
Цитата KILLER @
В С есть константы, на сколько я помню, так что такое оправдание не катит.
Константы в C это всего лишь переменные, в которые не разрешается писать. Размещаются они там в точности так же, как и переменные без модификатора const. То есть в одной единице трансляции пишется
ExpandedWrap disabled
    double const R2C = 273.15;
в остальных
ExpandedWrap disabled
    extern double const R2C;
иначе при сборке вылетает сообщение о дублировании имён.
То есть, только при трансляции одного куска известно значение этой константы, из остальных можно только прочитать его из памяти.
Соответственно нельзя использовать такую константу для определения, например, размера массива. Кроме того, такая константа не участвует в вычислении константных выражений.

Определение константы как
ExpandedWrap disabled
    static double const R2C = 273.15;
делает доступным её значение в каждой единице трансляции, но компилятор всё равно резервирует для каждой такой константы место (отдельное в каждой единице, где она определена), и тоже не разрешает использовать её для задания тех же размеров, и не вычисляет выражения с её использованием.

Некоторые компиляторы, конечно, позволяют себе соптимизировать использование таких констант, но это как раз нестандартное поведение.
Сообщение отредактировано: amk -
Всё написанное выше это всего лишь моё мнение, возможно ошибочное.
Цитата KILLER @
Нет, ты видимо все таки не смотрел Microsoft SDK, где goto вхерачен в макрос, который представляет из себя часть какой то то ли функции, то ли проверки, и потом таким же макросом расставлены метки?

Причём тут MS SDK? Я ответил на конкретный пример - когда с помощью goto переходят к очистке локальных ресурсов, то это вполне удобно и читабельно (если в языке нет иных для этого механизмов), в отличие от твоего исправления. А про примеры от MS я, в общем-то, речь не вёл, а просто спросил, где там говнокод с твоей точки зрения.

Цитата KILLER @
Напишу. Но не сейчас. Я сейчас занят. Но идея такова - избавится от вложенного цикла. Твой код синтетический и надуманный. Ты хочешь сказать его не реально по другому переписать никак? Я если что в него даже не в никал, просто по диагонале посмотрел не особо вдумываясь в смысл написанного.

Оно и видно. Код вполне нормальный, задача - прервать выполнение цикла, если что-то пошло не так. Т.е. хватит даже простого цикла (не обязательно двойного-тройного), из которого нужно переходить к очистке, чтобы твой паттерн с do..while перестал работать. Только не говори "не юзать циклы вообще" - такое будет даже от тебя неадекватно звучать :D
Подпись была включена в связи с окончанием срока наказания
Цитата KILLER @
ну может быть еще какую вещь упустил

Ага :lol: макро assert
У меня есть хороший макро для целей анализа ... бета-версий, а-ля:
ExpandedWrap disabled
    #define GuiCheckFatal() if (!Global.Error.isEmpty()) { QMessageBox::critical(0, QObject::tr("Внимание!"), Global.Error + QObject::tr("<hr>Файл: \"")+QFileInfo(__FILE__).fileName()+QObject::tr("\"<BR>Строка: ")+QString::number(__LINE__)); qCritical() << Global.Error + QObject::tr(" Файл: \"")+QFileInfo(__FILE__).fileName()+QObject::tr("\" Строка: ")+QString::number(__LINE__); Global.Error.clear(); qApp->closeAllWindows(); return; }

При условии перехвата записи в qCritical() и реализации записи в лог файл - мой макро божественен!
Не знаю что бы я делал без #define
Мои программные ништякиhttp://majestio.info
Цитата cppasm @
Чем он не в тему?
Ты же писал что

Он не в тему тем, что ты пришел, тему не читал, зато начал что то писать. Я тебе говорю - твой пример не в тему, и не привожу почему - чтоб ты взял и сам перечитал. А ты судя по всему не перечитал, делаешь глупое лицо и спрашиваешь - чем? Вот сиди и ломай голову. Раз тебе перечитывать лень.

Цитата cppasm @
Это печально что ты не приводишь конкретных примеров, а только бла бла бла...

Я дал полную информацию - для того, что бы ты мог открыть и посмотреть. Если тебе лень это делать - с чего ты взял что мне не будет лень это делать? Вот ты сейчас как раз занимаешься только бла бла бла, ты не прочел тему, ты не понимаешь о чем тут речь идет, зато свое бла бла бла вставляешь.

Цитата cppasm @
Во-первых код не надуманный, а упрощённый.

Надуманный.

Цитата cppasm @
Никогда при написании кода не возникало необходимости вывалиться из нескольких вложенных циклов?

Абсолютно никогда. Даже припомнить таких случаев не могу. Всегда обходился без этого треша. Более того, я тебе больше скажу - у меня никогда за 15 лет - не возникало даже мысли чтобы вот тут юзнуть goto, потому что без него вообще никак не сделать.

Ты может приведешь такой пример? А не просто надуманный говнокод? Который ты не в состоянии преписать по нормальному?

Цитата cppasm @
Напиши то же самое с do/while, for, break, continue и т.п. и без дублирования кода.

А зачем ты мне ставишь такие ограничения? Ты че, думаешь я тут распинатся буду и переписывать тебе с do/while? Ну извини, я не мыслю такими категориями как goto, я тебе больше скажу - он мне ниразу в жизни никогда не понадобился. И я даже не представляю задачи - где без него нельзя было бы обойтись. Ну не считая вот таких вот выдуманных говнокодов, или каких нибудь костылей - где по другому не перепишешь быстро.
По поводу кода - на держи:
ExpandedWrap disabled
    int iterateRow(void* mem, int col)
    {
            for(j=0; j<100; j++)
            {
              if(some_data[col][j]==SOME_VALUE)
                   return some_data[col][j];
              mem[col*100+j]=some_data[col][j];
            }
       return 0;
    }
     
    void main()
    {
        mem=malloc(size);
          // ...
          for(i=0; i<100; i++)
          {
              if( iterateRow(mem, i)==SOME_VALUE )
                   break;
          }
     
          free(mem);
          return 0;
     
    }


Цитата cppasm @
По ссылкам твоим ходил - нигде там такого нету.
В основном везде переход на Cleanup из середины функции.

Да никуда ты не ходил. Кому ты лапшу вешаешь? Максимум ты ткнул на пример с MSDN, и по "See Also" еще глянул пару примеров.

Цитата cppasm @
Во-первых код не надуманный, а упрощённый.

Надуманный, причем говнокод. Если ты по другому не можешь сразу написать - о чем может идти речь?
Если следовать твой логике - то в твоем коде можно придраться к каждой строчке, у тебя там все бессмысленно. Но я то понимаю - что твой код надуманный, и был приведен чтобы просто показать идею какую то там. Так что не говори что он не надуманный, в противном случае - будешь рассказывать почему памяти выделяется size, а циклы идут до 100, и почему не до конца инициализированный блок памяти, сразу же очищается, после выхода из цикла.

Цитата Qraizer @
Можно и говнокод писать. Но лучше не надо. А патерн, как бы тебе лично не хотелось, он патерн. Его знают, узнают с пол-взгляда и сразу понимают, что он делает и зачем вообще нужен.

Хорошо, кинь мне ссылку на описание этого паттерна, впервые о таком слышу. Может тоже буду применять у себя. А то я хочу из умной книжки почитать - его название, какие у него есть плюсы, какие у него есть минусы, и какие есть альтернативные варианты, когда его лучше использовать, а когда нет.
И не нужно отвечать на эти вопросы - ты же понимаешь что они риторические. Мне нужна именно ссылка на описание этого паттерна. Я хочу убедиться, что это именно паттерн, а не просто говнокод лентяев, которым лень переписывать по другому.

Цитата Qraizer @
По меньшей мере тем, что это не патерн обработки ошибок. А ещё тем, что обработка ошибок зачастую ломает структурность алгоритма. Напрочь. Попытки обернуть неструктурность алгоритма в фантик структурности наивны, т.к. наносят вред.

А зачем придумывать неструктурированный алгоритм? Или goto не ломает структурированность? Я что то ничего не понял.

Цитата OpenGL @
Причём тут MS SDK?

При том, что я писал про код микрософта:
Цитата KILLER @
Да вообще у майкрософта подход к программированию какой то нубско-студенческий. Всюду юзают goto и где не попадя макросы, даже вместо констант. Порой смотришь их MSDN или код какой нибудь функции и диву даешься - неужели там действительно тупарей берут, которые без макросов и goto писать не могут ниче.

Если они так пишут свое SDK, значит они ровно так же пишут свой продуктивный код. Более того - я с их кодом очень часто пересекаюсь, и вижу какой у них подход к написанию кода. И если бы это касалось только кода 80-х годов, у меня бы не было никаких притензий.

Цитата OpenGL @
Я ответил на конкретный пример - когда с помощью goto переходят к очистке локальных ресурсов, то это вполне удобно и читабельно (если в языке нет иных для этого механизмов), в отличие от твоего исправления. А про примеры от MS я, в общем-то, речь не вёл, а просто спросил, где там говнокод с твоей точки зрения.

И часто ты так делаешь? :lol: Что реально удобно? Если это удобно и читабельно - значит ты так же делаешь? Или ты просто с академической стороны вопроса судишь? Или ты - я так никогда не делаю, но это удобно? Нихрена это не удобно. Это напрочь ломает читабельность кода.

Цитата OpenGL @
А про примеры от MS я, в общем-то, речь не вёл, а просто спросил, где там говнокод с твоей точки зрения.

Везде. Я тебе уже отвечал. И привел алгоритм действий. Если ты его не осилил - это уже не мои проблемы.

Цитата OpenGL @
Оно и видно. Код вполне нормальный, задача - прервать выполнение цикла, если что-то пошло не так.

Здача может и стандартная, но вот реализация - говнокод. Что по другому никак нельзя прервать выполнение цикла? Лично для меня вот тот код выше, что привел cppasm, дикость. Я лично считаю что так пишут люди ограниченные в умственных способностях. Возможно я так думаю потому, что мне еще не приходилось страдать таким и сталкиваться с этим. А значит - либо такая ситуация - очень редкая и не стандартная и не стоит обсуждения. Либо пишут так говнокодеры, которым лень думать. Но ты если что не обижайся, это лично мое мнение. Я не претендую на истину, и в полне могу ошибаться.
Особенно если ты покажешь мне не синтетическую задачу, а какую нибудь боевую, где без этого goto, как без ifndef в кроссплатформенном коде. Может быть тогда я изменю свое мнение. Пока что для меня это говнокод.

Цитата OpenGL @
из которого нужно переходить к очистке, чтобы твой паттерн с do..while перестал работать. Только не говори "не юзать циклы вообще" - такое будет даже от тебя неадекватно звучать :D

Еще раз - do/while - Лично для меня воспринимается гораздо лучше и читабельнее, чем goto, потому что нет меток и скачков. У тебя есть цикл, и есть break, все. Тебе не нужно искать метку глазами, а блок где заканчивается цикл, мне и IDE подсветит на крайняк.

Добавлено
Цитата JoeUser @
У меня есть хороший макро для целей анализа ... бета-версий, а-ля:
CollapsedWrap disabledLine numbers off

Это отладочные средства. Про них речи не идет. То что есть у тебя, и то что ты применяешь для себя, и то что это никуда не идет - касается лично тебя. Соответственно ты можешь писать там как угодно, никто тебе слово не скажет. Вот если это попадает в прод, тогда другое дело.

Добавлено
Цитата cppasm @
Ничем этот паттерн не лучше goto которого ты так боишься

Да, и к слову, я goto не боюсь. Просто для меня это сродни кучке говна. Ты ведь не боишься говно? Но считаешь его противным? Вот примерно вот так для меня goto. Вижу goto - это значит, автор расписался в собственном бессилии и навалил кучку говнеца в коде.
Сообщение отредактировано: KILLER -
Цитата KILLER @
И часто ты так делаешь?

Попробуй ответить на этот вопрос самостоятельно. Тебе для этого надо знать только то, что я не пишу на Си - остальную информацию для ответа ты можешь получить из моих постов этой темы. :D

Цитата KILLER @
Я тебе уже отвечал.

Я знаю, что ты отвечал. Ты подумал что ли, что я это ещё раз спрашиваю? :lool: Да, я от тебя на данный конкретный вопрос ответ получил, он меня впоне устроил и новых вопросов по этому поводу у меня нет. Можно считать вопрос о говнокоде в MS SDK закрытым, или я всё ещё недостаточно ясно выразился, что я с этим не спорю от слова совсем? :D

Цитата KILLER @
Особенно если ты покажешь мне не синтетическую задачу, а какую нибудь боевую, где без этого goto, как без ifndef в кроссплатформенном коде. Может быть тогда я изменю свое мнение. Пока что для меня это говнокод.

Киля, перечитай внимательней. Простейший паттерн:
1) сложная инициализация локальных переменных
2) главные действия, которые могут прерваться из разных мест, после чего надо перейти в 3)
3) очистка того, что создали в 1)

твоим паттерном do..while более читабельным не сделать, если в 2 у тебя есть циклы, из которых ты можешь выходить сразу в 3). Ну и до кучи могу напомнить эту тему - в ней был пример, когда с помощью goto вообще заходят внутрь тройного цикла, и более читабельный вариант того примера, но без goto, никто, включая тебя, так и не родил.
Подпись была включена в связи с окончанием срока наказания
Цитата OpenGL @
Попробуй ответить на этот вопрос самостоятельно. Тебе для этого надо знать только то, что я не пишу на Си - остальную информацию для ответа ты можешь получить из моих постов этой темы. :D

Ну то есть никогда. К слову - когда я писал на Си, после С++ - да было больно, с непревычки, но и там - я как то обходился без goto. А значит такие "паттерны" просто говорят о том, что автору было лень придумывать что то другое и умное(ну бывает такое), либо он обычный быдлокодер, пишет на отвали.

Цитата OpenGL @
Киля, перечитай внимательней. Простейший паттерн:
1) сложная инициализация локальных переменных
2) главные действия, которые могут прерваться из разных мест, после чего надо перейти в 3)
3) очистка того, что создали в 1)

Ты сейчас просто сформулировал некий алгоритм, куда наложил некие ограничение, из которых как то следует, что самый простой способ реализовать именно этот алгоритм, путем использования goto. Но ведь у тебя не возникает ведь такой алгоритм на том языке на которым ты пишешь? Что, в Си нет средств обойти это без использования goto ? Хорошо, пусть бьет каждую сущность на отдельные функции какие то, блоки. Вот я беру пример с МСДНа с кучкой goto, это при том, что он тамписан на С++, т.к. юзаются классы/COM/еще какая нибудь фигня, и переписываю это все без goto. Вы же сейчас или специально или я не пойму, выдумываете какие то ограничения, которыми в реальной жизни вы не ограничены.

Добавлено
Цитата OpenGL @
твоим паттерном do..while более читабельным не сделать, если в 2 у тебя есть циклы, из которых ты можешь выходить сразу в 3)

Так в данном случае намеренно усложняется задача. Т.е. вместо того, чтобы посидеть подумать как всего этого избежать, и сделать код более удобочитаемым и расширяемым, вы решили юзать goto.

А что ты будешь делать(ну или Qraizer, cppasm, кто там еще топил? Fester) если дальше добавятся еще 10 вложенных циклов, и из каждого при определенном условии нужно выпрыгнуть на очистку ресурсов? Я так полагаю вы будете заводить 10 разный меток, и прыгать? Да? Судя по всему да. Отличный подход, и во что превратится этот код? Это будет все еще паттерн?

Цитата OpenGL @
Ну и до кучи могу напомнить эту тему - в ней был пример, когда с помощью goto вообще заходят внутрь тройного цикла, и более читабельный вариант того примера, но без goto, никто, включая тебя, так и не родил.

А пример найти можешь? Я помню там Qraizer его приводил, но я не помню смысл примера. Если на пример не накладываются ограничения - значит это исключительная ситуация. И ты сам прекрасно должен понимать, что запрыгивание внутрь тройного цикла - больше смахивает на какой то грязный хак или даже костыль в перемешку с говнокодом, чем на паттерн или обычный подход в программировании. Так что с этим примером так же мимо я думаю. Искать мне его лень.
Цитата KILLER @
К слову - когда я писал на Си, после С++ - да было больно, с непревычки, но и там - я как то обходился без goto. А значит такие "паттерны" просто говорят о том, что автору было лень придумывать что то другое и умное(ну бывает такое), либо он обычный быдлокодер, пишет на отвали.

Когда я писал на Си - тоже не возникало. Вот только писал я на нём программы в сотню-другую строк максимум. Если же заглянуть в любой крупный проект на нём (например,вот тебе первый попавшийся файл из nginx-а), то goto там - сплошь и рядом, и при этом куда переходит выполнение кода - прекрасно видно.

Цитата KILLER @
Но ведь у тебя не возникает ведь такой алгоритм на том языке на которым ты пишешь?

Такой алгоритм? Возникает постоянно, но см. выше - на си я не пишу, поэтому данный случай прекрасно разрруливается другими средствами.

Цитата KILLER @
Что, в Си нет средств обойти это без использования goto ?

Раз он там используется повсеместно - видимо, нет :-?

Цитата KILLER @
А пример найти можешь?

Я уже тему нашёл. Если тебе лень перечитывать 18 страниц, то мне тем более лень это делать :D Суть примера простая - есть тройной цикл со сложной логикой счётчиков (не просто for i,j,k = 0..n), он длинный, поэтому его можно прерывать. Но если он прервался - надо прочитать значения счётчиков, на которых мы остановились, после чего как ни в чём не бывало зайти внутрь циклов - всё просто и понятно. Структурный вариант в той теме был, но с goto он мог соревноваться только с краткостью записи, но никак не с понятностью (там сложная логика в условиях выхода из циклов, и неочевидный инкремент были).
Подпись была включена в связи с окончанием срока наказания
Цитата
А что ты будешь делать(ну или Qraizer, cppasm, кто там еще топил? Fester) если...

Я тебе уже много раз говорил, что если использование goto делает код более понятным, то момно и нужно использовать goto. Если ты дописываешь какие-то конструкции только ради того, чтобы избавиться от goto, то ты пишешь говнокод.
- Завтра или послезавтра придет фруктовый пароход из Мобила, - сказал Джонни. - А до той поры нам делать нечего.
- Но что вы намерены делать? Создать спрос?
- Много вы понимаете в политической экономии, - ответил консул довольно невежливо. - Спроса создать нельзя. Но можно создать условия, которые вызовут спрос.
Цитата KILLER @
Я так полагаю вы будете заводить 10 разный меток, и прыгать? Да?

Нет. У меня деструкторы есть для этого. И зачем 10 меток? Метка очистки обычно одна. Если их нужно больше, то я, если бы писал на си, подумал бы об упрощении, наверное.
Подпись была включена в связи с окончанием срока наказания
Цитата OpenGL @
Вот только писал я на нём программы в сотню-другую строк максимум. Если же заглянуть в любой крупный проект на нём (например,вот тебе первый попавшийся файл из nginx-а), то goto там - сплошь и рядом, и при этом куда переходит выполнение кода - прекрасно видно.

То есть если это файл из nginx - значит там автоматом не может быть говнокода? Я его начал мотать по твоей ссылке, не выдержал нажал поиск, первый же встретившийся goto - посмотри на саму функцию, ее по хорошему уже можно было только разбить на 3-4 функций. Зачем такие большие функции писать? Может быть от этого и юзают там goto? Кто то пишет крупные проекты в одной функции main, и считает что это норма. Я видел функцию длинной в 5 тысяч строк кода. Это что нормально? Если бы автор перепроектировал свой код, думаю можно было сделать его более удобочитаемым.
Сам файл 5 тыс строк кода. Это нормально? Ты так же бы это все написал? В таком стиле? Я не знаю, я не курил этот код, но думается мне, возможно один этот *.с файл превратился в 10 файлов или даже в подпроект. Я лично считаю это плохим подходом, когда у тебя файл в 5 тыс строк, там же черт ногу сломит. Потому что такой код потом сопровождать очень сложно. Если это автор писал для себя, и будет сам лично его сопровождать, то я тут спорить не буду, пусть хоть все 5 тыс строк кода пишет на одних goto в одной функции. Его право.

Цитата OpenGL @
Такой алгоритм? Возникает постоянно, но см. выше - на си я не пишу, поэтому данный случай прекрасно разрруливается другими средствами.

Тот, который ты придумал. Ну вот выше я переписал код cppasm, там похожая проблема. Мне мой подход нравится больше. При этом я вроде переписал в С стиле, не прибегая к средствам С++. Что я сделал не так?
Может вы сейчас придеретесь к количеству строчек? Типа у него 10, а у меня 20 ?

Цитата OpenGL @
Раз он там используется повсеместно - видимо, нет :-?

Где там? В С? Нет, не повсеместно. Но, изначально речь зашла про майкрософт, а у них не только в Си коде goto, открой ATL/MFC исходники посмотри. Что используя С++ нельзя обойтись без goto?

Цитата OpenGL @
Я уже тему нашёл. Если тебе лень перечитывать 18 страниц, то мне тем более лень это делать :D Суть примера простая - есть тройной цикл со сложной логикой счётчиков (не просто for i,j,k = 0..n), он длинный, поэтому его можно прерывать. Но если он прервался - надо прочитать значения счётчиков, на которых мы остановились, после чего как ни в чём не бывало зайти внутрь циклов - всё просто и понятно. Структурный вариант в той теме был, но с goto он мог соревноваться только с краткостью записи, но никак не с понятностью (там сложная логика в условиях выхода из циклов, и неочевидный инкремент были).

Понимаешь, лично я не ограничен каким либо одним средством и костылем. Возможно задачу стоило переписать на другом языке, возможно стоило вообще по другому ее сформулировать и решать совершенно с другим подходом. Там лишь обсуждалась, на сколько я помню, конкретная реализация, которую предлагалось переписать без goto. но ведь так можно написать абсолютно любой грязный хак, сказать вот есть вот именно вот такое условие - на перепиши без грязного хака. И ты скажешь - да, при такой постановке задачи, и при таких условиях - это решается только грязным хаком. Но это ведь не означает, что это единственно верное решение задачи в целом?

Цитата Fester @
Я тебе уже много раз говорил, что если использование goto делает код более понятным, то момно и нужно использовать goto

Так приведи мне хоть один пример, когда goto делает код более понятным?

Цитата OpenGL @
Нет. У меня деструкторы есть для этого. И зачем 10 меток?

Ну как зачем. Разные условия потому что, разное поведение должно быть в разных подциклах. Можно ведь сформулировать задачу по разному, и ты скажешь - а что вообще требуется? И почему задача сформулирована именно вот так, а не вот эдак. И ты будешь абсолютно прав. И вот это я вам и пишу, а вы рассказываете о каких то мифических вещах, приводя условяи с ограничениями. Вот есть вот у меня 5 вложенных циклов с тремя goto - перепеши чтоб 5 вложенных циклов осталось ,а goto исчез. А зачем так делать? Может быть проще вообще каждый подцикл вынести в отдельную функцию? Почему я должен переписывать именно вот так, а не кардинально менять алгоритм? Я вот это не понимаю.

Добавлено
К слову, вот пост https://forum.sources.ru/next/index.php?sho...dpost&p=3190250 Qraizer
Вот код:
ExpandedWrap disabled
    #include <windows.h>
    #include <io.h>
    #include <conio.h>
    #include <fstream>
    #include <iostream>
     
    int main()
    {
     int i, j, k, l;
     
     if (_access("savedstate.dat", 4) == 0)     // Проверить, нет ли сохранённого состояния от предыдущего запуска
     {                                             // Если есть, восстановить и продолжиться
       std::ifstream inFile("savedstate.dat");
       bool          ok = true;
     
       ok = ok && inFile.read(reinterpret_cast<char*>(&i), sizeof(i)).gcount() == sizeof(i);
       ok = ok && inFile.read(reinterpret_cast<char*>(&j), sizeof(j)).gcount() == sizeof(j);
       ok = ok && inFile.read(reinterpret_cast<char*>(&k), sizeof(k)).gcount() == sizeof(k);
       ok = ok && inFile.read(reinterpret_cast<char*>(&l), sizeof(l)).gcount() == sizeof(l);
       if (ok && (inFile.good() || inFile.eof()))
       {
         std::cout << "The saved state is successfully restored." << std::endl;
         goto resume;
       }
       else return std::cerr << "The saved state restoring error. State file is wrong." << std::endl,
                   1;
     }
     
     for (i=0; i<10; ++i)
     {
       for (j=i; j<10; ++j)
       {
         for (k=j; k<10; ++k)
         {
           for (l=k; l<10; ++l)
           {
    resume:
             if (kbhit() && getch() == '\x1B')     // Проверить, не просят ли нас ESCпом прерваться
             {                                     // Если да, сохранить состояние и выйти
               if (_access("savedstate.dat", 2) == 0) remove("savedstate.dat");
            
               std::ofstream outFile("savedstate.dat");
               bool ok = true;
            
               ok = ok && outFile.write(reinterpret_cast<char*>(&i), sizeof(i)).good();
               ok = ok && outFile.write(reinterpret_cast<char*>(&j), sizeof(j)).good();
               ok = ok && outFile.write(reinterpret_cast<char*>(&k), sizeof(k)).good();
               ok = ok && outFile.write(reinterpret_cast<char*>(&l), sizeof(l)).good();
               if (!(ok && (outFile.good() || outFile.eof())))
                 return std::cerr << "The state saving error." << std::endl,
                       1;
               return std::cout << "The state successfully saved." << std::endl,
                      2;
             }
     
             /* ... */
     
             std::cout << "i = " << i << ", j = " << j << ", k = " << k << ", l = " << l << std::endl;
             Sleep(1);
           }
         }
       }
     }
     
     if (_access("savedstate.dat", 2) == 0) remove("savedstate.dat");
     return 0;
    }

Действительно, что тут не понятного. Без goto переписать ну просто не реально. :ph34r:

Добавлено
Причем это не Сишный код, а самый что ни на есть С++сный.

Добавлено
Прод код майкрософта из atlmfc:
ExpandedWrap disabled
    inline HRESULT CSecurityDescriptor::SetPrivilege(
        _In_z_ LPCTSTR privilege,
        _In_ BOOL bEnable,
        _In_ HANDLE hToken)
    {
        TOKEN_PRIVILEGES tpPrevious;
        TOKEN_PRIVILEGES tp;
        DWORD  cbPrevious = sizeof(TOKEN_PRIVILEGES);
        LUID   luid;
        HANDLE hTokenUsed;
     
        if (!LookupPrivilegeValue(NULL, privilege, &luid ))
            goto _Error;
     
        // if no token specified open process token
        if (hToken != 0)
            hTokenUsed = hToken;
        else
            if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hTokenUsed))
                goto _Error;
     
        tp.PrivilegeCount = 1;
        tp.Privileges[0].Luid = luid;
        tp.Privileges[0].Attributes = 0;
     
        memset(&tpPrevious, 0, sizeof(tpPrevious));
     
        if (!AdjustTokenPrivileges(hTokenUsed, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &tpPrevious, &cbPrevious))
            goto _Error_CloseHandle;
     
        tpPrevious.PrivilegeCount = 1;
        tpPrevious.Privileges[0].Luid = luid;
     
        if (bEnable)
            tpPrevious.Privileges[0].Attributes |= SE_PRIVILEGE_ENABLED;
        else
            tpPrevious.Privileges[0].Attributes &= ~SE_PRIVILEGE_ENABLED;
     
        if (!AdjustTokenPrivileges(hTokenUsed, FALSE, &tpPrevious, cbPrevious, NULL, NULL))
            goto _Error_CloseHandle;
     
        if(hToken == 0)
            CloseHandle(hTokenUsed);
     
        return S_OK;
     
        HRESULT hr;
     
    _Error:
        hr = AtlHresultFromLastError();
        return hr;
     
    _Error_CloseHandle:
        hr = AtlHresultFromLastError();
        if (hToken == 0)
            CloseHandle(hTokenUsed);
        return hr;
    }


Еще один продакшн код майкрософта из atlmfc
ExpandedWrap disabled
        inline BOOL Parse(_In_z_ LPCTSTR lpszUrl)
        {
            ATLENSURE(lpszUrl != NULL);
     
            TCHAR ch;
            BOOL bGotScheme = FALSE;
            BOOL bGotUserName = FALSE;
            BOOL bGotHostName = FALSE;
            BOOL bGotPortNumber = FALSE;
            CAtlString strCurrentUrl;
            TCHAR* szCurrentUrl = strCurrentUrl.GetBuffer(ATL_URL_MAX_URL_LENGTH+6);
            TCHAR* pszCurrentUrl = szCurrentUrl;
            size_t nUrlSize = 0;
     
            BOOL bInsideSquareBrackets = FALSE;
     
            //parse lpszUrl using szCurrentUrl to store temporary data
     
            //this loop will get the following if it exists:
            //<protocol>://user:pass@server:port
            while ((ch = *lpszUrl) != '\0')
            {
                if (nUrlSize >= ATL_URL_MAX_URL_LENGTH+5)
                    goto error;
     
                if (ch == ':' && !bInsideSquareBrackets)
                {
                    //3 cases:
                    //(1) Just encountered a scheme
                    //(2) Port number follows
                    //(3) Form of username:password@
     
                    // Check to see if we've just encountered a scheme
                    *pszCurrentUrl = '\0';
                    if (!bGotScheme)
                    {
                        if (!SetSchemeName(szCurrentUrl))
                            goto error;
     
                        //Set a flag to avoid checking for
                        //schemes everytime we encounter a :
                        bGotScheme = TRUE;
     
                        if (*(lpszUrl+1) == '/')
                        {
                            if (*(lpszUrl+2) == '/')
                            {
                                //the mailto scheme cannot have a '/' following the "mailto:" portion
                                if (bGotScheme && m_nScheme == ATL_URL_SCHEME_MAILTO)
                                    goto error;
     
                                //Skip these characters and continue
                                lpszUrl+= 2;
                            }
                            else
                            {
                                //it is an absolute path
                                //no domain name, port, username, or password is allowed in this case
                                //break to loop that gets path
                                lpszUrl++;
                                pszCurrentUrl = szCurrentUrl;
                                nUrlSize = 0;
                                break;
                            }
                        }
     
                        //reset pszCurrentUrl
                        pszCurrentUrl = szCurrentUrl;
                        nUrlSize = 0;
                        lpszUrl++;
     
                        //if the scheme is file, skip to getting the path information
                        if (m_nScheme == ATL_URL_SCHEME_FILE)
                            break;
                        continue;
                    }
                    else if (!bGotUserName || !bGotPortNumber)
                    {
                        //It must be a username:password or a port number
                        *pszCurrentUrl = '\0';
     
                        pszCurrentUrl = szCurrentUrl;
                        nUrlSize = 0;
                        TCHAR tmpBuf[ATL_URL_MAX_PASSWORD_LENGTH+1];
                        TCHAR* pTmpBuf = tmpBuf;
                        int nCnt = 0;
     
                        //get the user or portnumber (break on either '/', '@', or '\0'
                        while (((ch = *(++lpszUrl)) != '/') && (ch != '@') && (ch != '\0'))
                        {
                            if (nCnt >= ATL_URL_MAX_PASSWORD_LENGTH)
                                goto error;
     
                            *pTmpBuf++ = ch;
                            nCnt++;
                        }
                        *pTmpBuf = '\0';
     
                        //if we broke on a '/' or a '\0', it must be a port number
                        if (!bGotPortNumber && (ch == '/' || ch == '\0'))
                        {
                            //the host name must immediately preced the port number
                            if (!SetHostName(szCurrentUrl))
                                goto error;
     
                            //get the port number
                            m_nPortNumber = (ATL_URL_PORT) _ttoi(tmpBuf);
     
                            bGotPortNumber = bGotHostName = TRUE;
                        }
                        else if (!bGotUserName && ch=='@')
                        {
                            //otherwise it must be a username:password
                            if (!SetUserName(szCurrentUrl) || !SetPassword(tmpBuf))
                                goto error;
     
                            bGotUserName = TRUE;
                            lpszUrl++;
                        }
                        else
                        {
                            goto error;
                        }
                    }
                }
                else if (ch == '@')
                {
                    if (bGotUserName)
                        goto error;
     
                    //type is userinfo@
                    *pszCurrentUrl = '\0';
                    if (!SetUserName(szCurrentUrl))
                        goto error;
     
                    bInsideSquareBrackets = FALSE;
     
                    bGotUserName = TRUE;
                    lpszUrl++;
                    pszCurrentUrl = szCurrentUrl;
                    nUrlSize = 0;
                }
                else if (ch == '/' || ch == '?' || (!*(lpszUrl+1)))
                {
                    //we're at the end of this loop
                    //set the domain name and break
                    if (!*(lpszUrl+1) && ch != '/' && ch != '?')
                    {
                        if (nUrlSize >= ATL_URL_MAX_URL_LENGTH+4)
                            goto error;
     
                        *pszCurrentUrl++ = ch;
                        nUrlSize++;
                        lpszUrl++;
                    }
                    *pszCurrentUrl = '\0';
                    if (!bGotHostName)
                    {
                        if (!SetHostName(szCurrentUrl))
                            goto error;
                    }
                    pszCurrentUrl = szCurrentUrl;
                    nUrlSize = 0;
                    break;
                }
                else
                {
                    if (ch == '[' && bGotScheme && !bGotHostName)
                        bInsideSquareBrackets = TRUE;
                    else if (ch == ']')
                        bInsideSquareBrackets = FALSE;
     
                    *pszCurrentUrl++ = ch;
                    lpszUrl++;
                    nUrlSize++;
                }
            }
     
            if (!bGotScheme)
                goto error;
     
            //Now build the path
            while ((ch = *lpszUrl) != '\0')
            {
                if (nUrlSize >= ATL_URL_MAX_URL_LENGTH+5)
                    goto error;
     
                //break on a '#' or a '?', which delimit "extra information"
                if (m_nScheme != ATL_URL_SCHEME_FILE && (ch == '#' || ch == '?'))
                {
                    break;
                }
                *pszCurrentUrl++ = ch;
                nUrlSize++;
                lpszUrl++;
            }
            *pszCurrentUrl = '\0';
     
            if (*szCurrentUrl != '\0' && !SetUrlPath(szCurrentUrl))
                goto error;
     
            pszCurrentUrl = szCurrentUrl;
            nUrlSize = 0;
     
            while ((ch = *lpszUrl++) != '\0')
            {
                if (nUrlSize >= ATL_URL_MAX_URL_LENGTH+5)
                    goto error;
     
                *pszCurrentUrl++ = ch;
                nUrlSize++;
            }
     
            *pszCurrentUrl = '\0';
            if (*szCurrentUrl != '\0' && !SetExtraInfo(szCurrentUrl))
                goto error;
     
            switch(m_nScheme)
            {
                case ATL_URL_SCHEME_FILE:
                    m_nPortNumber = ATL_URL_INVALID_PORT_NUMBER;
                    break;
                case ATL_URL_SCHEME_NEWS:
                    m_nPortNumber = ATL_URL_INVALID_PORT_NUMBER;
                    break;
                case ATL_URL_SCHEME_MAILTO:
                    m_nPortNumber = ATL_URL_INVALID_PORT_NUMBER;
                    break;
                default:
                    if (!bGotPortNumber)
                        m_nPortNumber = (unsigned short)AtlGetDefaultUrlPort(m_nScheme);
            }
     
            return TRUE;
     
    error:
            InitFields();
            return FALSE;
     
        }

Ну конечно, это ведь все писалось в 80-ые года, когда кроме goto никто ничего не знал. Ну и для обратной совместимости осталось.

Это продакшн код!!! Не примеры, не SDK и не MSDN, если вы мне не верите, посмотрите у себя.
Конечно, как тут без goto переписать то по другому? Ну просто нереально сложно. Проще ведь goto впихнуть.


А это! Это просто шедевр!!! cppasm, помнишь обвинял меня в том, что я бла бла бла, просто вчера я был реально занят, и не было у меня времени смотреть, а вот сейчас нашел немножко времени.
Оцени, бла бла бла:
ExpandedWrap disabled
    BOOL CWnd::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
    {
        LRESULT lResult = 0;
        union MessageMapFunctions mmf;
        mmf.pfn = 0;
        CInternalGlobalLock winMsgLock;
        // special case for commands
        if (message == WM_COMMAND)
        {
            if (OnCommand(wParam, lParam))
            {
                lResult = 1;
                goto LReturnTrue;
            }
            return FALSE;
        }
     
        if (message == WM_CREATE && m_pDynamicLayout != NULL)
        {
            ASSERT_VALID(m_pDynamicLayout);
     
            if (!m_pDynamicLayout->Create(this))
            {
                delete m_pDynamicLayout;
                m_pDynamicLayout = NULL;
            }
            else
            {
                InitDynamicLayout();
            }
        }
     
        // special case for notifies
        if (message == WM_NOTIFY)
        {
            NMHDR* pNMHDR = (NMHDR*)lParam;
            if (pNMHDR->hwndFrom != NULL && OnNotify(wParam, lParam, &lResult))
                goto LReturnTrue;
            return FALSE;
        }
     
        // special case for activation
        if (message == WM_ACTIVATE)
            _AfxHandleActivate(this, wParam, CWnd::FromHandle((HWND)lParam));
     
        // special case for set cursor HTERROR
        if (message == WM_SETCURSOR &&
            _AfxHandleSetCursor(this, (short)LOWORD(lParam), HIWORD(lParam)))
        {
            lResult = 1;
            goto LReturnTrue;
        }
     
       // special case for windows that contain windowless ActiveX controls
       BOOL bHandled;
     
       bHandled = FALSE;
       if ((m_pCtrlCont != NULL) && (m_pCtrlCont->m_nWindowlessControls > 0))
       {
          if (((message >= WM_MOUSEFIRST) && (message <= AFX_WM_MOUSELAST)) ||
             ((message >= WM_KEYFIRST) && (message <= WM_IME_KEYLAST)) ||
             ((message >= WM_IME_SETCONTEXT) && (message <= WM_IME_KEYUP)))
          {
             bHandled = m_pCtrlCont->HandleWindowlessMessage(message, wParam, lParam, &lResult);
          }
       }
       if (bHandled)
       {
          goto LReturnTrue;
       }
     
        switch (message)
        {
        case WM_SIZE:
            {
                ResizeDynamicLayout();
     
                CHwndRenderTarget* pRenderTarget = GetRenderTarget();
                if (pRenderTarget != NULL && pRenderTarget->IsValid())
                {
                    pRenderTarget->Resize(CD2DSizeU(UINT32(LOWORD(lParam)), UINT32(HIWORD(lParam))));
                    RedrawWindow();
                }
            }
            break;
     
        case WM_PAINT:
            if (DoD2DPaint())
            {
                lResult = 1;
                goto LReturnTrue;
            }
            break;
     
        case WM_ERASEBKGND:
            if (m_pRenderTarget != NULL && m_pRenderTarget->IsValid())
            {
                lResult = 1;
                goto LReturnTrue;
            }
            break;
        }
     
        const AFX_MSGMAP* pMessageMap; pMessageMap = GetMessageMap();
        UINT iHash; iHash = (LOWORD((DWORD_PTR)pMessageMap) ^ message) & (iHashMax-1);
        winMsgLock.Lock(CRIT_WINMSGCACHE);
        AFX_MSG_CACHE* pMsgCache; pMsgCache = &_afxMsgCache[iHash];
        const AFX_MSGMAP_ENTRY* lpEntry;
        if (message == pMsgCache->nMsg && pMessageMap == pMsgCache->pMessageMap)
        {
            // cache hit
            lpEntry = pMsgCache->lpEntry;
            winMsgLock.Unlock();
            if (lpEntry == NULL)
                return FALSE;
     
            // cache hit, and it needs to be handled
            if (message < 0xC000)
                goto LDispatch;
            else
                goto LDispatchRegistered;
        }
        else
        {
            // not in cache, look for it
            pMsgCache->nMsg = message;
            pMsgCache->pMessageMap = pMessageMap;
     
            for (/* pMessageMap already init'ed */; pMessageMap->pfnGetBaseMap != NULL;
                pMessageMap = (*pMessageMap->pfnGetBaseMap)())
            {
                // Note: catch not so common but fatal mistake!!
                //      BEGIN_MESSAGE_MAP(CMyWnd, CMyWnd)
                ASSERT(pMessageMap != (*pMessageMap->pfnGetBaseMap)());
                if (message < 0xC000)
                {
                    // constant window message
                    if ((lpEntry = AfxFindMessageEntry(pMessageMap->lpEntries,
                        message, 0, 0)) != NULL)
                    {
                        pMsgCache->lpEntry = lpEntry;
                        winMsgLock.Unlock();
                        goto LDispatch;
                    }
                }
                else
                {
                    // registered windows message
                    lpEntry = pMessageMap->lpEntries;
                    while ((lpEntry = AfxFindMessageEntry(lpEntry, 0xC000, 0, 0)) != NULL)
                    {
                        UINT* pnID = (UINT*)(lpEntry->nSig);
                        ASSERT(*pnID >= 0xC000 || *pnID == 0);
                            // must be successfully registered
                        if (*pnID == message)
                        {
                            pMsgCache->lpEntry = lpEntry;
                            winMsgLock.Unlock();
                            goto LDispatchRegistered;
                        }
                        lpEntry++;      // keep looking past this one
                    }
                }
            }
     
            pMsgCache->lpEntry = NULL;
            winMsgLock.Unlock();
            return FALSE;
        }
     
    LDispatch:
        ASSERT(message < 0xC000);
     
        mmf.pfn = lpEntry->pfn;
     
        switch (lpEntry->nSig)
        {
        default:
            ASSERT(FALSE);
            break;
        case AfxSig_l_p:
            {
                CPoint point(lParam);      
                lResult = (this->*mmf.pfn_l_p)(point);
                break;
            }      
        case AfxSig_b_D_v:
            lResult = (this->*mmf.pfn_b_D)(CDC::FromHandle(reinterpret_cast<HDC>(wParam)));
            break;
     
        case AfxSig_l_D_u:
            lResult = (this->*mmf.pfn_l_D_u)(CDC::FromHandle(reinterpret_cast<HDC>(wParam)), (UINT)lParam);
            break;
     
        case AfxSig_b_b_v:
            lResult = (this->*mmf.pfn_b_b)(static_cast<BOOL>(wParam));
            break;
     
        case AfxSig_b_u_v:
            lResult = (this->*mmf.pfn_b_u)(static_cast<UINT>(wParam));
            break;
     
        case AfxSig_b_h_v:
            lResult = (this->*mmf.pfn_b_h)(reinterpret_cast<HANDLE>(wParam));
            break;
     
        case AfxSig_i_u_v:
            lResult = (this->*mmf.pfn_i_u)(static_cast<UINT>(wParam));
            break;
     
        case AfxSig_C_v_v:
            lResult = reinterpret_cast<LRESULT>((this->*mmf.pfn_C_v)());
            break;
     
        case AfxSig_v_u_W:
            (this->*mmf.pfn_v_u_W)(static_cast<UINT>(wParam),
                CWnd::FromHandle(reinterpret_cast<HWND>(lParam)));
            break;
     
        case AfxSig_u_u_v:
            lResult = (this->*mmf.pfn_u_u)(static_cast<UINT>(wParam));
            break;
     
        case AfxSig_b_v_v:
            lResult = (this->*mmf.pfn_b_v)();
            break;
     
        case AfxSig_b_W_uu:
            lResult = (this->*mmf.pfn_b_W_u_u)(CWnd::FromHandle(reinterpret_cast<HWND>(wParam)),
                LOWORD(lParam), HIWORD(lParam));
            break;
     
        case AfxSig_b_W_COPYDATASTRUCT:
            lResult = (this->*mmf.pfn_b_W_COPYDATASTRUCT)(
                CWnd::FromHandle(reinterpret_cast<HWND>(wParam)),
                reinterpret_cast<COPYDATASTRUCT*>(lParam));
            break;
     
        case AfxSig_b_v_HELPINFO:
            lResult = (this->*mmf.pfn_b_HELPINFO)(reinterpret_cast<LPHELPINFO>(lParam));
            break;
     
        case AfxSig_CTLCOLOR:
            {
                // special case for OnCtlColor to avoid too many temporary objects
                ASSERT(message == WM_CTLCOLOR);
                AFX_CTLCOLOR* pCtl = reinterpret_cast<AFX_CTLCOLOR*>(lParam);
                CDC dcTemp;
                dcTemp.m_hDC = pCtl->hDC;
                CWnd wndTemp;
                wndTemp.m_hWnd = pCtl->hWnd;
                UINT nCtlType = pCtl->nCtlType;
                // if not coming from a permanent window, use stack temporary
                CWnd* pWnd = CWnd::FromHandlePermanent(wndTemp.m_hWnd);
                if (pWnd == NULL)
                {
                    // determine the site of the OLE control if it is one
                    COleControlSite* pSite;
                    if (m_pCtrlCont != NULL && (pSite = (COleControlSite*)
                        m_pCtrlCont->m_siteMap.GetValueAt(wndTemp.m_hWnd)) != NULL)
                    {
                        wndTemp.m_pCtrlSite = pSite;
                    }
     
                    pWnd = &wndTemp;
                }
                HBRUSH hbr = (this->*mmf.pfn_B_D_W_u)(&dcTemp, pWnd, nCtlType);
                // fast detach of temporary objects
                dcTemp.m_hDC = NULL;
                wndTemp.m_hWnd = NULL;
                lResult = reinterpret_cast<LRESULT>(hbr);
            }
            break;
     
        case AfxSig_CTLCOLOR_REFLECT:
            {
                // special case for CtlColor to avoid too many temporary objects
                ASSERT(message == WM_REFLECT_BASE+WM_CTLCOLOR);
                AFX_CTLCOLOR* pCtl = reinterpret_cast<AFX_CTLCOLOR*>(lParam);
                CDC dcTemp;
                dcTemp.m_hDC = pCtl->hDC;
                UINT nCtlType = pCtl->nCtlType;
                HBRUSH hbr = (this->*mmf.pfn_B_D_u)(&dcTemp, nCtlType);
                // fast detach of temporary objects
                dcTemp.m_hDC = NULL;
                lResult = reinterpret_cast<LRESULT>(hbr);
            }
            break;
     
        case AfxSig_i_u_W_u:
            lResult = (this->*mmf.pfn_i_u_W_u)(LOWORD(wParam),
                CWnd::FromHandle(reinterpret_cast<HWND>(lParam)), HIWORD(wParam));
            break;
     
        case AfxSig_i_uu_v:
            lResult = (this->*mmf.pfn_i_u_u)(LOWORD(wParam), HIWORD(wParam));
            break;
     
        case AfxSig_i_W_uu:
            lResult = (this->*mmf.pfn_i_W_u_u)(CWnd::FromHandle(reinterpret_cast<HWND>(wParam)),
                LOWORD(lParam), HIWORD(lParam));
            break;
     
        case AfxSig_i_v_s:
            lResult = (this->*mmf.pfn_i_s)(reinterpret_cast<LPTSTR>(lParam));
            break;
     
        case AfxSig_i_v_S:
            lResult = (this->*mmf.pfn_i_S)(reinterpret_cast<LPCTSTR>(lParam));
            break;
     
        case AfxSig_v_F_b:
            (this->*mmf.pfn_v_F_b)(CFont::FromHandle(reinterpret_cast<HFONT>(wParam)), (BOOL)LOWORD(lParam));
            break;
     
        case AfxSig_h_v_v:
            {
                HANDLE handle = (this->*mmf.pfn_h_v)();
                lResult = reinterpret_cast<LRESULT>(handle);
            }
            break;
     
        case AfxSig_h_b_h:
            {
                HANDLE handle = (this->*mmf.pfn_h_b_h)(static_cast<BOOL>(wParam), reinterpret_cast<HANDLE>(lParam));
                lResult = reinterpret_cast<LRESULT>(handle);
            }
            break;
     
        case AfxSig_h_h_h:
            {
                HANDLE handle = (this->*mmf.pfn_h_h_h)(reinterpret_cast<HANDLE>(wParam), reinterpret_cast<HANDLE>(lParam));
                lResult = reinterpret_cast<LRESULT>(handle);
            }
            break;
     
        case AfxSig_l_w_l:
            lResult = (this->*mmf.pfn_l_w_l)(wParam, lParam);
            break;
     
        case AfxSig_l_uu_M:
            lResult = (this->*mmf.pfn_l_u_u_M)(LOWORD(wParam), HIWORD(wParam),
                CMenu::FromHandle(reinterpret_cast<HMENU>(lParam)));
            break;
            
        case AfxSig_v_b_h:
            (this->*mmf.pfn_v_b_h)(static_cast<BOOL>(wParam),
                reinterpret_cast<HANDLE>(lParam));
            break;
     
        case AfxSig_v_h_v:
            (this->*mmf.pfn_v_h)(reinterpret_cast<HANDLE>(wParam));
            break;
     
        case AfxSig_v_h_h:
            (this->*mmf.pfn_v_h_h)(reinterpret_cast<HANDLE>(wParam),
                reinterpret_cast<HANDLE>(lParam));
            break;
     
        case AfxSig_v_v_v:
            (this->*mmf.pfn_v_v)();
            break;
     
        case AfxSig_v_u_v:
            (this->*mmf.pfn_v_u)(static_cast<UINT>(wParam));
            break;
     
        case AfxSig_v_up_v:
            (this->*mmf.pfn_v_up)(static_cast<UINT_PTR>(wParam));
            break;
     
        case AfxSig_v_u_u:
            (this->*mmf.pfn_v_u_u)(static_cast<UINT>(wParam), static_cast<UINT>(lParam));
            break;
     
        case AfxSig_v_uu_v:
            (this->*mmf.pfn_v_u_u)(LOWORD(wParam), HIWORD(wParam));
            break;
     
        case AfxSig_v_v_ii:
            (this->*mmf.pfn_v_i_i)(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
            break;
     
        case AfxSig_v_u_uu:
            (this->*mmf.pfn_v_u_u_u)(static_cast<UINT>(wParam), LOWORD(lParam), HIWORD(lParam));
            break;
     
        case AfxSig_v_u_ii:
            (this->*mmf.pfn_v_u_i_i)(static_cast<UINT>(wParam), LOWORD(lParam), HIWORD(lParam));
            break;
     
        case AfxSig_v_w_l:
            (this->*mmf.pfn_v_w_l)(wParam, lParam);
            break;
     
        case AfxSig_MDIACTIVATE:
            (this->*mmf.pfn_v_b_W_W)(m_hWnd == reinterpret_cast<HWND>(lParam),
                CWnd::FromHandle(reinterpret_cast<HWND>(lParam)),
                CWnd::FromHandle(reinterpret_cast<HWND>(wParam)));
            break;
     
        case AfxSig_MDINext:
            (this->*mmf.pfn_v_W_b)(CWnd::FromHandle(reinterpret_cast<HWND>(wParam)), static_cast<BOOL>(lParam));
            break;
     
        case AfxSig_v_D_v:
            (this->*mmf.pfn_v_D)(CDC::FromHandle(reinterpret_cast<HDC>(wParam)));
            break;
     
        case AfxSig_v_M_v:
            (this->*mmf.pfn_v_M)(CMenu::FromHandle(reinterpret_cast<HMENU>(wParam)));
            break;
     
        case AfxSig_v_M_ub:
            (this->*mmf.pfn_v_M_u_b)(CMenu::FromHandle(reinterpret_cast<HMENU>(wParam)),
                GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
            break;
     
        case AfxSig_v_W_v:
            (this->*mmf.pfn_v_W)(CWnd::FromHandle(reinterpret_cast<HWND>(wParam)));
            break;
     
        case AfxSig_v_v_W:
            (this->*mmf.pfn_v_W)(CWnd::FromHandle(reinterpret_cast<HWND>(lParam)));
            break;
     
        case AfxSig_v_W_uu:
            (this->*mmf.pfn_v_W_u_u)(CWnd::FromHandle(reinterpret_cast<HWND>(wParam)), LOWORD(lParam),
                HIWORD(lParam));
            break;
     
        case AfxSig_v_W_p:
            {
                CPoint point(lParam);
                (this->*mmf.pfn_v_W_p)(CWnd::FromHandle(reinterpret_cast<HWND>(wParam)), point);
            }
            break;
     
        case AfxSig_v_W_h:
            (this->*mmf.pfn_v_W_h)(CWnd::FromHandle(reinterpret_cast<HWND>(wParam)),
                    reinterpret_cast<HANDLE>(lParam));
            break;
     
        case AfxSig_ACTIVATE:
            (this->*mmf.pfn_v_u_W_b)(LOWORD(wParam),
                CWnd::FromHandle(reinterpret_cast<HWND>(lParam)), HIWORD(wParam));
            break;
     
        case AfxSig_SCROLL:
        case AfxSig_SCROLL_REFLECT:
            {
                // special case for WM_VSCROLL and WM_HSCROLL
                ASSERT(message == WM_VSCROLL || message == WM_HSCROLL ||
                    message == WM_VSCROLL+WM_REFLECT_BASE || message == WM_HSCROLL+WM_REFLECT_BASE);
                int nScrollCode = (short)LOWORD(wParam);
                int nPos = (short)HIWORD(wParam);
                if (lpEntry->nSig == AfxSig_SCROLL)
                    (this->*mmf.pfn_v_u_u_W)(nScrollCode, nPos,
                        CWnd::FromHandle(reinterpret_cast<HWND>(lParam)));
                else
                    (this->*mmf.pfn_v_u_u)(nScrollCode, nPos);
            }
            break;
     
        case AfxSig_v_v_s:
            (this->*mmf.pfn_v_s)(reinterpret_cast<LPTSTR>(lParam));
            break;
     
        case AfxSig_v_u_cs:
            (this->*mmf.pfn_v_u_cs)(static_cast<UINT>(wParam), reinterpret_cast<LPCTSTR>(lParam));
            break;
     
        case AfxSig_OWNERDRAW:
            (this->*mmf.pfn_v_i_s)(static_cast<int>(wParam), reinterpret_cast<LPTSTR>(lParam));
            lResult = TRUE;
            break;
     
        case AfxSig_i_i_s:
            lResult = (this->*mmf.pfn_i_i_s)(static_cast<int>(wParam), reinterpret_cast<LPTSTR>(lParam));
            break;
     
        case AfxSig_u_v_p:
            {
                CPoint point(lParam);
                lResult = (this->*mmf.pfn_u_p)(point);
            }
            break;
     
        case AfxSig_u_v_v:
            lResult = (this->*mmf.pfn_u_v)();
            break;
     
        case AfxSig_v_b_NCCALCSIZEPARAMS:
            (this->*mmf.pfn_v_b_NCCALCSIZEPARAMS)(static_cast<BOOL>(wParam),
                reinterpret_cast<NCCALCSIZE_PARAMS*>(lParam));
            break;
     
        case AfxSig_v_v_WINDOWPOS:
            (this->*mmf.pfn_v_v_WINDOWPOS)(reinterpret_cast<WINDOWPOS*>(lParam));
            break;
     
        case AfxSig_v_uu_M:
            (this->*mmf.pfn_v_u_u_M)(LOWORD(wParam), HIWORD(wParam), reinterpret_cast<HMENU>(lParam));
            break;
     
        case AfxSig_v_u_p:
            {
                CPoint point(lParam);
                (this->*mmf.pfn_v_u_p)(static_cast<UINT>(wParam), point);
            }
            break;
     
        case AfxSig_SIZING:
            (this->*mmf.pfn_v_u_pr)(static_cast<UINT>(wParam), reinterpret_cast<LPRECT>(lParam));
            lResult = TRUE;
            break;
     
        case AfxSig_MOUSEWHEEL:
            lResult = (this->*mmf.pfn_b_u_s_p)(LOWORD(wParam), (short)HIWORD(wParam),
                CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
            if (!lResult)
                return FALSE;
            break;
        case AfxSig_MOUSEHWHEEL:
            (this->*mmf.pfn_MOUSEHWHEEL)(LOWORD(wParam), (short)HIWORD(wParam),
                CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
            break;
        case AfxSig_l:
            lResult = (this->*mmf.pfn_l_v)();
            if (lResult != 0)
                return FALSE;
            break;
        case AfxSig_u_W_u:
            lResult = (this->*mmf.pfn_u_W_u)(CWnd::FromHandle(reinterpret_cast<HWND>(wParam)), static_cast<UINT>(lParam));
            break;
        case AfxSig_v_u_M:
            (this->*mmf.pfn_v_u_M)(static_cast<UINT>(wParam), CMenu::FromHandle(reinterpret_cast<HMENU>(lParam)));
            break;
        case AfxSig_u_u_M:
            lResult = (this->*mmf.pfn_u_u_M)(static_cast<UINT>(wParam), CMenu::FromHandle(reinterpret_cast<HMENU>(lParam)));
            break;
        case AfxSig_u_v_MENUGETOBJECTINFO:
            lResult = (this->*mmf.pfn_u_v_MENUGETOBJECTINFO)(reinterpret_cast<MENUGETOBJECTINFO*>(lParam));
            break;
        case AfxSig_v_M_u:
            (this->*mmf.pfn_v_M_u)(CMenu::FromHandle(reinterpret_cast<HMENU>(wParam)), static_cast<UINT>(lParam));
            break;
        case AfxSig_v_u_LPMDINEXTMENU:
            (this->*mmf.pfn_v_u_LPMDINEXTMENU)(static_cast<UINT>(wParam), reinterpret_cast<LPMDINEXTMENU>(lParam));
            break;
        case AfxSig_APPCOMMAND:
            (this->*mmf.pfn_APPCOMMAND)(CWnd::FromHandle(reinterpret_cast<HWND>(wParam)), static_cast<UINT>(GET_APPCOMMAND_LPARAM(lParam)), static_cast<UINT>(GET_DEVICE_LPARAM(lParam)), static_cast<UINT>(GET_KEYSTATE_LPARAM(lParam)));
            lResult = TRUE;
            break;
        case AfxSig_RAWINPUT:
            (this->*mmf.pfn_RAWINPUT)(static_cast<UINT>(GET_RAWINPUT_CODE_WPARAM(wParam)), reinterpret_cast<HRAWINPUT>(lParam));
            break;
        case AfxSig_u_u_u:
            lResult = (this->*mmf.pfn_u_u_u)(static_cast<UINT>(wParam), static_cast<UINT>(lParam));
            break;
        case AfxSig_u_u_l:
            lResult = (this->*mmf.pfn_u_u_l)(static_cast<UINT>(wParam), lParam);
            break;
        case AfxSig_MOUSE_XBUTTON:
            (this->*mmf.pfn_MOUSE_XBUTTON)(static_cast<UINT>(GET_KEYSTATE_WPARAM(wParam)), static_cast<UINT>(GET_XBUTTON_WPARAM(wParam)), CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
            lResult = TRUE;
            break;
        case AfxSig_MOUSE_NCXBUTTON:
            (this->*mmf.pfn_MOUSE_NCXBUTTON)(static_cast<short>(GET_NCHITTEST_WPARAM(wParam)), static_cast<UINT>(GET_XBUTTON_WPARAM(wParam)), CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
            lResult = TRUE;
            break;
        case AfxSig_INPUTLANGCHANGE:
            (this->*mmf.pfn_INPUTLANGCHANGE)(static_cast<UINT>(wParam), static_cast<UINT>(lParam));
            lResult = TRUE;
            break;
        case AfxSig_INPUTDEVICECHANGE:
            (this->*mmf.pfn_INPUTDEVICECHANGE)(LOWORD(wParam), reinterpret_cast<HANDLE>(lParam));
            break;
        case AfxSig_v_u_hkl:
            (this->*mmf.pfn_v_u_h)(static_cast<UINT>(wParam), reinterpret_cast<HKL>(lParam));
            break;
        case AfxSig_b_v_ii:
            lResult = (this->*mmf.pfn_b_v_ii)(GET_Y_LPARAM(lParam), GET_X_LPARAM(lParam));
            break;
        }
        goto LReturnTrue;
     
    LDispatchRegistered:    // for registered windows messages
        ASSERT(message >= 0xC000);
        ASSERT(sizeof(mmf) == sizeof(mmf.pfn));
        mmf.pfn = lpEntry->pfn;
        lResult = (this->*mmf.pfn_l_w_l)(wParam, lParam);
     
    LReturnTrue:
        if (pResult != NULL)
            *pResult = lResult;
        return TRUE;
    }

Как тебе? Любишь такой код сопровождать? Или сам такой код и пишешь?

Ну и вишенка на тортик:
C:\Program Files\Microsoft SDKs\Windows\v7.0\Samples\com\administration\spy\comspyctl\Adminwrap.Cpp
ExpandedWrap disabled
    #include "stdafx.h"
    #include "Adminwrap.h"
    #include <comadmin.h>
    #include <assert.h>
     
    #define if_failed_exit(HR)      do { if FAILED(HR) goto exit; } while (false)
    #define exit_with_result(HR)    do { hr = HR; goto exit; } while (false)

:lol: :lol: :lol: :lol:
Сообщение отредактировано: KILLER -
Цитата KILLER @
По поводу кода - на держи

И нафига ты проверку дублируешь?
Так понятней читать что-ли, для тех кто с первого раза не понимает? :)
От того что ты кусок кода в функцию вынес как-то лучше не стало.


Цитата KILLER @
Он не в тему тем, что ты пришел, тему не читал, зато начал что то писать. Я тебе говорю - твой пример не в тему, и не привожу почему - чтоб ты взял и сам перечитал.

Это называется съехал. Понятно.

Добавлено
Цитата KILLER @
А это! Это просто шедевр!!! cppasm, помнишь обвинял меня в том, что я бла бла бла

И где тут анонсированное:
Цитата KILLER @
goto вхерачен в макрос, который представляет из себя часть какой то то ли функции, то ли проверки, и потом таким же макросом расставлены метки?

Кривой тут только последний пример, остальное нормально читается.
Цитата
Так приведи мне хоть один пример, когда goto делает код более понятным?

Ты сам привел такой пример:

Цитата
inline HRESULT CSecurityDescriptor::SetPrivilege

Вариант с goto читаем. Использование do{...}while(false); сделало бы этот код хуже читаемым.
- Завтра или послезавтра придет фруктовый пароход из Мобила, - сказал Джонни. - А до той поры нам делать нечего.
- Но что вы намерены делать? Создать спрос?
- Много вы понимаете в политической экономии, - ответил консул довольно невежливо. - Спроса создать нельзя. Но можно создать условия, которые вызовут спрос.
К слову - действительно причём здесь SDK?
Это не SDK, это сэмплы из SDK. Я их например вообще не ставлю никогда, и что?
И почему SDK v7.0 а не v7.1, чтоб другим проверить сложнее было?
Цитата cppasm @
И нафига ты проверку дублируешь?

Чтоб выйти из внешнего цикла, я ведь даже подход к решению задачи не менял. Можно переписать и мой код по другому. Я тебе его написал на коленке, чтобы показать идею, как можно переписать твой код без goto, примерно так же как и ты мне его написал на коленке. Возможно там вообще можно было обойтись еще проще. Я не знаю, мне пока не интересно придумывать 100500 разных вариантов решения твоей задачи.

Цитата cppasm @
Так понятней читать что-ли, для тех кто с первого раза не понимает? :)

У тебя выход по goto идет из вложенного цикла за внешний цикл. Поэтому я сделал там вторую проверку, просто твой вложенный цикл обернул в отдельную функцию.

Цитата cppasm @
От того что ты кусок кода в функцию вынес как-то лучше не стало.

Стало. Код стал намного понятнее, так как там уже не двойной цикл не пойми зачем идет, а появилась какая то логика происходящего + мы избавились от goto и вырвиглазного кода.

Цитата cppasm @
Это называется съехал. Понятно.

Хорошо, на держи бла бла бла:
Цитата KILLER @
Возможно в каких то там исключительных случаях - когда тебе нужно выйти из 4-ого по вложенности цикла - оно и упрощает понимание кода, но в тех примерах где они его используют, там и без goto обойтись не составляет проблем, без нарушения структуры исполнения программы.

Ты теперь понял - почему ты свой пример привел не в тему? И то - этот мой коментарий, если еще не понятно с оговоркой - "Если вот уже вот так все спроектировано, и другие решения подразумевают слишком много телодвижений или будут слишком сложные". Потому как я вообще стараюсь не писать больше двух вложенных циклов.

Цитата cppasm @
И где тут анонсированное:

Повылазило? Ну хорошо еще раз:
ExpandedWrap disabled
        #include "stdafx.h"
        #include "Adminwrap.h"
        #include <comadmin.h>
        #include <assert.h>
        #define if_failed_exit(HR)      do { if FAILED(HR) goto exit; } while (false) //<<<<<<<<<<<<<<<< goto вхерачен в макрос, который представляет из себя часть какой то то ли функции, то ли проверки
        #define exit_with_result(HR)    do { hr = HR; goto exit; } while (false)     //<<<<<<<<<<<<<<<< goto вхерачен в макрос, который представляет из себя часть какой то то ли функции, то ли проверки


Цитата cppasm @
Кривой тут только последний пример, остальное нормально читается.

Нормально читается? :wall: А что имея под рукой классы, кучу идиом и паттернов - по другому нельзя нормально переписать? А с использованием лямбд из нового стандарта, так даже можно и классы не применять, функции очистки и RAII можно клепать прямо на лету, где тебе нужно, без написания всяких оберток.

Например из последнего, то что было с goto и я переписывал без goto:
Мой код:
ExpandedWrap disabled
        DWORD COMUtility::SetAccountRights(const std::wstring& sUser, const std::wstring& sPrivilege)
        {
            auto LSAHandleDeleter = [](LSA_HANDLE* hPolicy)
            {
                if (hPolicy && *hPolicy)
                    LsaClose(*hPolicy);
            };
     
            std::unique_ptr<LSA_HANDLE, decltype(LSAHandleDeleter)> smartLSAHandle(nullptr, LSAHandleDeleter);
            LSA_HANDLE                                              rawLSAHandle = nullptr;
            LSA_OBJECT_ATTRIBUTES                                   objectAttributes = { 0 };
            std::unique_ptr<SID>                                    psidPrincipal;
            LSA_UNICODE_STRING                                      lsaPrivilegeString = { 0 };
            WCHAR                                                   wszPrivilege[256] = { 0 };
            DWORD                                                   dwReturnValue = ERROR_SUCCESS;
     
            StringCchCopy(wszPrivilege, (sPrivilege.size() * sizeof(wchar_t)) + 1, sPrivilege.c_str());
     
            dwReturnValue = LsaOpenPolicy(NULL, &objectAttributes, POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES, &rawLSAHandle);
            dwReturnValue = LsaNtStatusToWinError(dwReturnValue);
     
            smartLSAHandle.reset(std::move(&rawLSAHandle));
     
            if (dwReturnValue != ERROR_SUCCESS)
                return dwReturnValue;
     
            psidPrincipal = GetPrincipalSID(sUser, dwReturnValue);
            if (dwReturnValue != ERROR_SUCCESS)
                return dwReturnValue;
     
            lsaPrivilegeString.Length = (USHORT)(wcslen(wszPrivilege) * sizeof(WCHAR));
            lsaPrivilegeString.MaximumLength = (USHORT)(lsaPrivilegeString.Length + sizeof(WCHAR));
            lsaPrivilegeString.Buffer = wszPrivilege;
     
            dwReturnValue = LsaAddAccountRights(*smartLSAHandle, psidPrincipal.get(), &lsaPrivilegeString, 1);
            dwReturnValue = LsaNtStatusToWinError(dwReturnValue);
     
            return dwReturnValue;
        }


Оригинал от майкрософта:
ExpandedWrap disabled
     * NAME: SetAccountRights                                                    *
     * --------------------------------------------------------------------------*
     * DESCRIPTION: Sets the account right for a given user.                     *
    \*---------------------------------------------------------------------------*/
    DWORD SetAccountRights (
        LPTSTR tszUser,
        LPTSTR tszPrivilege
        )
    {
        LSA_HANDLE            hPolicy            = NULL;
        LSA_OBJECT_ATTRIBUTES objectAttributes   = {0};
        PSID                  psidPrincipal      = NULL;
        LSA_UNICODE_STRING    lsaPrivilegeString = {0};
        WCHAR                 wszPrivilege [256] = {0};
        DWORD                dwReturnValue       = ERROR_SUCCESS;
     
    #ifdef _UNICODE
        StringCchCopy (wszPrivilege, RTL_NUMBER_OF(wszPrivilege),tszPrivilege);
    #else
        STR2UNI (wszPrivilege, tszPrivilege);
    #endif
     
        dwReturnValue = LsaOpenPolicy (NULL,
                                       &objectAttributes,
                                       POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES,
                                       &hPolicy);
                                      
        dwReturnValue = LsaNtStatusToWinError(dwReturnValue);
     
        if (dwReturnValue != ERROR_SUCCESS) goto CLEANUP;
     
        dwReturnValue = GetPrincipalSID (tszUser, &psidPrincipal);
        if (dwReturnValue != ERROR_SUCCESS) goto CLEANUP;
     
        lsaPrivilegeString.Length = (USHORT) (wcslen (wszPrivilege) * sizeof (WCHAR));
        lsaPrivilegeString.MaximumLength = (USHORT) (lsaPrivilegeString.Length + sizeof (WCHAR));
        lsaPrivilegeString.Buffer = wszPrivilege;
     
        dwReturnValue = LsaAddAccountRights (hPolicy,
                                             psidPrincipal,
                                             &lsaPrivilegeString,
                                             1);
     
        dwReturnValue = LsaNtStatusToWinError(dwReturnValue);
     
        if (dwReturnValue != ERROR_SUCCESS) goto CLEANUP;
        
     
    CLEANUP:
     
        if(psidPrincipal) free (psidPrincipal);
        if(hPolicy) LsaClose (hPolicy);
     
        return dwReturnValue;
    }

И я сейчас не упрекаю их за то, что они там лямбды не повпихивали, или что они там std::wstring не использовали. Я тебе просто показываю как можно переписать без goto. Пусть этот код у них Сишный, но ведь С++сный код , что я привел выше - написан в том же стиле.
Ты считаешь это нормальным? А для меня это не нормально. Для меня более понятно и привычно то, как переписал я. Хотя возможно, и я не отрицаю у меня вырвиглазный код и его можно переписать еще лучше и круче. У меня не было цели рефакторить все, я избавился от goto и от ручного выделения/освобождения памяти.

Цитата Fester @
Вариант с goto читаем. Использование do{...}while(false); сделало бы этот код хуже читаемым.

Зачем переписывать на do while? Я вот по другому переписал. Мне мой подход - более понятен, чем этот оцтой.

Добавлено
Цитата cppasm @
К слову - действительно причём здесь SDK?
Это не SDK, это сэмплы из SDK. Я их например вообще не ставлю никогда, и что?
И почему SDK v7.0 а не v7.1, чтоб другим проверить сложнее было?

Посмотри другие версии. Если человек так пишет в семплах - то он так же будет писать в проде. Ну не можешь ты в проде писать вот так, а в семплах вот так. Это уже какой то троллинг получается.
Сообщение отредактировано: KILLER -
Цитата
Я вот по другому переписал. Мне мой подход - более понятен, чем этот оцтой.

Во-первых, твой вариант - не эквивалентен варианту от MS. У них в клинапе есть еще
ExpandedWrap disabled
    if(psidPrincipal) free (psidPrincipal);
а ты про это почему-то забыл ;)
Во-вторых, лямбды появились не так давно. Или ты полагаешь, что как только появилась новая цаца, так сразу МС должны переписать все библиотеки?
- Завтра или послезавтра придет фруктовый пароход из Мобила, - сказал Джонни. - А до той поры нам делать нечего.
- Но что вы намерены делать? Создать спрос?
- Много вы понимаете в политической экономии, - ответил консул довольно невежливо. - Спроса создать нельзя. Но можно создать условия, которые вызовут спрос.
Цитата KILLER @
Повылазило? Ну хорошо еще раз

Ты попроще общаться не пробовал?
Вот покажи конкретно где там
Цитата KILLER @
и потом таким же макросом расставлены метки

В противном случае у кого повылазило станет очевидно.
Сообщение отредактировано: cppasm -
Цитата Fester @
Во-первых, твой вариант - не эквивалентен варианту от MS. У них в клинапе есть еще
CollapsedWrap disabledLine numbers off

if(psidPrincipal) free (psidPrincipal);

а ты про это почему-то забыл ;)

Нет не забыл. Просто ты видимо С++ не знаешь.

Цитата Fester @
Во-вторых, лямбды появились не так давно. Или ты полагаешь, что как только появилась новая цаца, так сразу МС должны переписать все библиотеки?

А ты не читатель?
До лямбд уже 100 лет как успешно применяется идиома RAII. Почему MFC/ATL изначально не спроектировать на основе этой идиомы? Зачем там пихать goto ?

Цитата cppasm @
Ты попроще общаться не пробовал?

Если ты не читатель - как еще обращаться? Меня бесит когда человек не читает, но мнение имеет.

Цитата cppasm @
В противном случае у кого повылазило станет очевидно.

А тебе не очевидно зачем там этот макрос написан?

Добавлено
Еще один треш от майкрософта:
ExpandedWrap disabled
    #define __LONGSTRING(string) L##string
    #define LONGSTRING(string) __LONGSTRING(string)
     
    //Goes to CLEANUP on Failure
    #define CHECK_HR(hr)            \
        if(FAILED(hr))              \
            goto CLEANUP
     
    //Goes to CLEANUP on Failure, and displays any ErrorInfo
    #define XCHECK_HR(hr)                                               \
    {                                                                   \
        if( g_dwFlags & DISPLAY_METHODCALLS )                           \
            fwprintf(stderr, LONGSTRING(#hr) L"\n");                    \
        if(FAILED(myHandleResult(hr, LONGSTRING(__FILE__), __LINE__)))  \
            goto CLEANUP;                                               \
    }
    #define CHECK_MEMORY(hr, pv)    \
    {                               \
        if(!pv)                     \
        {                           \
            hr = E_OUTOFMEMORY;     \
            CHECK_HR(hr);           \
        }                           \
    }
Цитата KILLER @
По поводу кода - на держи:
...
Ну вот и говнокоду прибыло. KILLER, ты в натуре считаешь, что код от такой переделки выиграл? В чём? Наглядности? Скорости? Объёму? Ото ж, ради галочки. Попробуй теперь вот тут:
ExpandedWrap disabled
    int copyFile(const char* src, const char* dst)
    {
      void *buf = NULL;
      FILE *inF = NULL;
      FILE *ouF = NULL;
      size_t readed, written;
     
      buf = malloc(BUF_SIZE);
      inF = fopen(src, "rb");
      ouF = fopen(dst, "wb");
     
      if (buf == NULL) goto cleanup;
      if (inF == NULL) goto cleanup;
      if (ouF == NULL) goto cleanup;
     
      readed = fread(buf, 1, BUF_SIZE, inF);
      while (!feof(inF) || readed != 0)
      {
        written = fwrite(buf, 1, readed, ouF);
        if (written != readed) goto cleanup;
        readed = fread(buf, 1, BUF_SIZE, inF);
      }
      return 1;
     
    cleanup:
      if (ouF != NULL) fclose(ouF);
      if (inF != NULL) fclose(inF);
      if (buf != NULL) free(buf);
     
      return 0;
    }
С примерами в MSDN такая же хрень, их без __leave нормально не написать.
Цитата KILLER @
Хорошо, кинь мне ссылку на описание этого паттерна, впервые о таком слышу.
Керниган, Ричи. Язык C, раздел "3.9. Оператор GOTO и метки"
Цитата KILLER @
Может тоже буду применять у себя.
Не стоит. Хотя для слабеньких встроенных систем он и сегодня полезен, фактически за пределамиы POSIX, в котором отсутствует SEH или его аналог, он уже не применяется. Да-да-да, но смирись, что примеры в MSDN никто переписывать не будет.

Добавлено
Цитата KILLER @
Я так полагаю вы будете заводить 10 разный меток, и прыгать? Да? Судя по всему да.
А вот и нет. См. код выше. Ты ж не заводишь 10 finally... или заводишь? <_<
Сообщение отредактировано: Qraizer -
Одни с годами умнеют, другие становятся старше.
Цитата Qraizer @
Ну вот и говнокоду прибыло. KILLER, ты в натуре считаешь, что код от такой переделки выиграл?

В восприятии - да выиграл. Его стало проще воспринимать. Искать глазами метку - это треш, особенно если код не из 4 строчек, как привел cppasm.

Цитата Qraizer @
Керниган, Ричи. Язык C, раздел "3.9. Оператор GOTO и метки"

Цитата

В языке "C" предусмотрен и оператор GOTO, которым беско-
нечно злоупотребляют, и метки для ветвления. С формальной
точки зрения оператор GOTO никогда не является необходимым,
и на практике почти всегда можно обойтись без него.


Дальше читать не стал. Даже K&R считают что в Си им злоупотребляют, и практически всегда можно обойтись без него. ЧТД.

Цитата Qraizer @
Да-да-да, но смирись, что примеры в MSDN никто переписывать не будет.

Так я не прошу чтоб они их переписывали, они новые клепают на том же goto. Я тут уже привел достаточно кода из ATL/MFC что писалось исключительно на С++, для демонстрации их подхода.

Цитата Qraizer @

int copyFile(const char* src, const char* dst)
{
void *buf = NULL;
FILE *inF = NULL;
FILE *ouF = NULL;
size_t readed, written;

buf = malloc(BUF_SIZE);
inF = fopen(src, "rb");
ouF = fopen(dst, "wb");

if (buf == NULL) goto cleanup;
if (inF == NULL) goto cleanup;
if (ouF == NULL) goto cleanup;

readed = fread(buf, 1, BUF_SIZE, inF);
while (!feof(inF) || readed != 0)
{
written = fwrite(buf, 1, readed, ouF);
if (written != readed) goto cleanup;
readed = fread(buf, 1, BUF_SIZE, inF);
}
return 1;

cleanup:
if (ouF != NULL) fclose(ouF);
if (inF != NULL) fclose(inF);
if (buf != NULL) free(buf);

return 0;
}

Выше ведь приводил уже:
ExpandedWrap disabled
     auto LSAHandleDeleter = [](LSA_HANDLE* hPolicy)
            {
                if (hPolicy && *hPolicy)
                    LsaClose(*hPolicy);
            };

Поменяй название LSA_HANDLE на FILE и все перепишется на ура. На крайний случай это все легко переписывается с помощью идиомы RAII. И не нужно следить забыл я закрыть файл или удалить буфер.
Сообщение отредактировано: KILLER -
Цитата OpenGL @
Структурный вариант в той теме был, но с goto он мог соревноваться только с краткостью записи, но никак не с понятностью (там сложная логика в условиях выхода из циклов, и неочевидный инкремент были).
Ещё он писался в несколько приёмов и отлаживался. С goto написалось с первого раза и заработало без отладки.
Одни с годами умнеют, другие становятся старше.
Цитата Qraizer @
Ещё он писался в несколько приёмов и отлаживался. С goto написалось с первого раза и заработало без отладки.

А зачем тогда проектировать всякие идиомы, патерны? Можно и без них ведь все написать с первого раза не отлаживаясь, в одной функции main с помощью всяких goto, главное блок схему нарисовать, чтоб не запутаться потом :D
Сообщение отредактировано: KILLER -
Цитата KILLER @
Если человек так пишет в семплах - то он так же будет писать в проде.
Далеко не уверен. Как должны выглядеть примеры, я уже говорил выше. Я как-то натыкался на такой вопрос MS-ному блогеру, мол, почему у вас в примерах постоянно memset() для инициализации структур вместо простого = {0}, на что был получен ровно такой же ответ. Во-первых, = {0} легко пропустить и не заметить при чтении, в результате код, адаптированный читателем под свои нужды, с большей вероятностью будет содержать ошибку. Во-вторых, читатель может писать на каком-нибудь VB или Turbo Pascal for Windows и C читает со словарём, поэтому memset() не поймёт если, то пойдёт читать справку, а нагуглить = {0} ему будет куда сложнее. В результате у них было принято в примерах MSDN писать всё максимально линейно и топорно, и неважно, что пример при этом разрастётся в разы по объёму.

Добавлено
Цитата KILLER @
Дальше читать не стал.
Я ожидал такой реакции. Как это по-интернетному: прочитать эпиграф и закрыть книгу.

Добавлено
Цитата KILLER @
Выше ведь приводил уже:
Ты язык поменял. Если б я писал на C++, я б написал
ExpandedWrap disabled
    bool copyFile(const char* src, const char* dst)
    {
      std::vector<char> buf(BUF_SIZE);
      std::ifstream inF(src);
      std::ofstream ouF(dst);
     
      if (inF.is_open()) return false;
      if (ouF.is_open()) return false;
     
      inF.read(&buf.front(), buf.size());
      while (inF.good()) || inF.eof() && inF.gcount() != 0)
      {
        ouF.write(&buf.front(), inF.gcount());
        if (ouF.pcount() != inF.gcount()) return false;
        inF.read(&buf.front(), buf.size());
      }
      return true;
    }

Хотя кого я обманываю:
ExpandedWrap disabled
    bool copyFile(const char* src, const char* dst)
    {
      std::ifstream inF(src);
      std::ofstream ouF(dst);
     
      if (inF.is_open()) return false;
      if (ouF.is_open()) return false;
     
      ouF << inF.rdbuf();
     
      return ouF.pcount() == inF.gcount();
    }
Сообщение отредактировано: Qraizer -
Одни с годами умнеют, другие становятся старше.
Цитата Qraizer @
Я ожидал такой реакции. Как это по-интернетному: прочитать эпиграф и закрыть книгу.

Дело в том, что я ожидал увидеть не обсирание goto K&R, а конкретно описание какого нибудь паттерна.
Ну что то типа - "Все ругают goto за то то и за то то. Но! Есть один паттерн, в реализации которого goto просто не заменимая вещь. И так рассмотрим пример...".
Но ты привел как раз ссылку на то что "Все кругом злоупотребляют goto, и вообще он полный оцтой, и всегда можно обойтись без него, тем не менее, ща мы вам покажем пару вещей, где в принципе - если лень что то писать, можно и обойтись goto, с кучей оговорок...".

Например чуваки тут от нефиг делать пишут эмуляцию RAII и исключений на С, и как то обходятся без goto -> https://github.com/psevon/exceptions-and-raii-in-c
А вы пытаетесь отмазать применение goto, даже там, где ему вообще не место.
Цитата KILLER @
Но ты привел как раз ссылку на то что "Все кругом злоупотребляют goto, и вообще он полный оцтой, и всегда можно обойтись без него, тем не менее, ща мы вам покажем пару вещей, где в принципе - если лень что то писать, можно и обойтись goto, с кучей оговорок...".
Ну так прочти следующие два предложения :lol:

К тому же в цитате написано "почти всегда", ты, видимо, пропустил. Случайно.
Сообщение отредактировано: Qraizer -
Одни с годами умнеют, другие становятся старше.
Цитата Qraizer @
Ты язык поменял. Если б я писал на C++, я б написал

Ну например на гцц есть такая штука -> http://echorand.me/site/notes/articles/c_c...ttribute_c.html
Пример взят по ссылке выше:
ExpandedWrap disabled
    # include <stdlib.h>
    # include <stdio.h>
     
    # define TMP_FILE "/tmp/tmp.file"
     
    void free_buffer(char **buffer)
    {
      printf("Freeing buffer\n");
      free(*buffer);
    }
     
    void cleanup_file(FILE **fp)
    {
      printf("Closing file\n");
      fclose(*fp);
     
      printf("Deleting the file\n");
      remove(TMP_FILE);
    }
     
    int main(int argc, char **argv)
    {
      char *buffer __attribute__ ((__cleanup__(free_buffer))) = malloc(20);
      FILE *fp __attribute__ ((__cleanup__(cleanup_file)));
     
      fp = fopen(TMP_FILE, "w+");
      
      if (fp != NULL)
        fprintf(fp, "%s", "Alinewithnospaces");
     
      fflush(fp);
      fseek(fp, 0L, SEEK_SET);
      fscanf(fp, "%s", buffer);
      printf("%s\n", buffer);
      
      return 0;
    }

Я работал с apache там ЕМНИП это уже реализовано из каропки. Но я на чистом С уже не писал лет 5. Если бы я на нем писал, я бы давно уже написал себе пару вспомогательных функций конкретно для работы с ресурсами в стиле RAII. Сейчас у меня попросту нет времени, переделывать и переписывать ваши примеры.

Добавлено
Цитата Qraizer @
К тому же в цитате написано "почти всегда", ты, видимо, пропустил. Случайно.

Нет не пропустил. И даже выше я в принципе соглашался с использованием goto в качестве костылей, когда переписать правильно нет времени.

Добавлено
Цитата Qraizer @
Ну так прочти следующие два предложения :lol:

А я именно от туда и процитировал свою фразу, если ты не понял :rolleyes:
И ниже они пишут:
Цитата

Хотя мы не являемся в этом вопросе догматиками, нам все
же кажется, что если и нужно использовать оператор GOTO, то
весьма умеренно.


То что пишите вы - не похоже на весьма умерено, это больше похоже на "как правило", особенно если рассматривать это как паттерн.
Сообщение отредактировано: KILLER -
Во-первых, пишите на C++. Хотя бы из-за RAII. Исключения и RTTI можно отрубить.
Во-вторых, даже если вы пишите на C, рассмотрите варианты с __finally для ms-компилятора и __attribute__ ((__cleanup__(f))) для gcc/clang.
В-третьих, если таки "чистый Си", то смотрите по обстоятельствам. Иногда действительно без goto получается больше говнокода. Но злоупотреблять не стоит.

Мне кажется, что большинство с этим согласится, нет?
О чем спор?
Сообщение отредактировано: D_KEY -
"If someone claims to have the perfect programming language, he is either a fool or a salesman or both"(c) Bjarne Stroustrup
Цитата D_KEY @
О чем спор?

О том, что майкрософт пишет говнокод и злоупотребляет #define/goto. Мне доказывают что они не пишут говнокод, а goto - нужен для реализации патерна обработки ошибок и клинапа. А я с ними не согласен. Привожу по моему мнению говнокод из ATL/MFC/SDK/MSDN - а мне доказывают что это не говнокод, а хороший, удобочитаемый код. Вот об этом спор.
Нет, KILLER. Тебе доказывают, что любая крайность – это плохо. Неважно, на каком краю эта крайность.

Добавлено
P.S. Если ты не обратил внимание. Я нигде на примеры из продакшн кода не говорил, что так и надо, но говорил за примеры в MSDN. А почему так в продакшн, не знаю. Может быть код писался в расчёте на слабо оптимизирующие компиляторы с плохо оптимизированными RTL, технологиям ATL и MFC в обед сто лет исполняется. И тем не менее не считаю это смертельным. т.к. код соответствует патерну обработки ошибок.
Одни с годами умнеют, другие становятся старше.
Цитата Qraizer @
Тебе доказывают, что любая крайность – это плохо. Неважно, на каком краю эта крайность.

Ну так объясни мне, зачем в ATL/MFC майкрософт юзает паттерн с goto, вместо идиомы RAII? И злоупотребляет дефайнами? Там что классов нет?

Цитата Qraizer @
Я нигде на примеры из продакшн кода не говорил, что так и надо, но говорил за примеры в MSDN.

Дак у них в MSDN с классами - ровно то же самое. Конечно можно отмазаться сказать - это всего лишь справка, и вообще похер как там написано. Они наняли отдельных индусов, которые занимаются исключительно написанием семплов для SDK/MSDN и в прод они не лезут. Ну и что бы я тогда возразил? Я бы скорее всего согласился что наверное так и есть.

Цитата Qraizer @
Может быть код писался в расчёте на слабо оптимизирующие компиляторы с плохо оптимизированными RTL, технологиям ATL и MFC в обед сто лет исполняется. И тем не менее не считаю это смертельным. т.к. код соответствует патерну обработки ошибок.

Угу, в то время - когда можно обойтись RAII.
Цитата KILLER @
Я его начал мотать по твоей ссылке, не выдержал нажал поиск, первый же встретившийся goto - посмотри на саму функцию, ее по хорошему уже можно было только разбить на 3-4 функций. Зачем такие большие функции писать?

И зачем разбивать? Функция с "первым же встретившится goto" предельно понятна.

Цитата KILLER @
Что я сделал не так?

Начал переписывать, не поняв, какую проблему решает goto, очевидно :D

Цитата KILLER @
Где там? В С? Нет, не повсеместно.

Да ладно. Ну вот тебе ещё примеры из ядра линукса, git, quake 3. Дальше искать влом. Но, ты, конечно, можешь считать, что авторы всех этих программ - дебилы и говнокодеры, не догадавшиеся, что можно было просто обратиться к KILLER-у с исходников с вопросом "как переписать без goto" - я спорить с этим даже не буду :D

Цитата KILLER @
Понимаешь, лично я не ограничен каким либо одним средством и костылем.

О чём ты? Ты вполне себе ограничен - религиозной заморочкой "писать код без goto", которая, очевидно, мешает в определённых случаях писать более компакнтный и читаемый код :D

Цитата KILLER @
Действительно, что тут не понятного. Без goto переписать ну просто не реально.

Перепиши. Вот зуб даю - если у тебя получится не хуже, чем с goto, то тебе тут не только я - половина участников темы плюсы поставит. От себя вообще три плюса обещаю :D

Цитата KILLER @
Причем это не Сишный код, а самый что ни на есть С++сный.

И что? Или ты не заметил, что тут решается задача "запрыгнуть внутрь циклов", и это не goto cleanup, смысла котоого в плюсах немного? :D
Подпись была включена в связи с окончанием срока наказания
Цитата OpenGL @
Цитата KILLER @
Действительно, что тут не понятного. Без goto переписать ну просто не реально.

Перепиши. Вот зуб даю - если у тебя получится не хуже, чем с goto, то тебе тут не только я - половина участников темы плюсы поставит. От себя вообще три плюса обещаю :D

Ну честно говоря тот код вряд ли прошел бы pull request во всех компаниях/командах где я работал :)
А в чем суть задачи?
"If someone claims to have the perfect programming language, he is either a fool or a salesman or both"(c) Bjarne Stroustrup
Цитата D_KEY @
А в чем суть задачи?

Цитата OpenGL @
Суть примера простая - есть тройной цикл со сложной логикой счётчиков (не просто for i,j,k = 0..n), он длинный, поэтому его можно прерывать. Но если он прервался - надо прочитать значения счётчиков, на которых мы остановились, после чего как ни в чём не бывало зайти внутрь циклов - всё просто и понятно. Структурный вариант в той теме был, но с goto он мог соревноваться только с краткостью записи, но никак не с понятностью (там сложная логика в условиях выхода из циклов, и неочевидный инкремент были).
Подпись была включена в связи с окончанием срока наказания
Цитата OpenGL @
А вообще странная голосовалка и варианты

Сначала думал примерами. Потом подумал, начнут обсуждать примеры вместо сабжа. Но теперь всё-таки думаю, что надо было примерами...
Простейший случай

ExpandedWrap disabled
    #define MACROMAX(x,y) \
        ((x < y)?y:x)

ExpandedWrap disabled
    template <typename T1, typename T2>
    T1 templatemax(T1 x, T2 y)
    {
        return (x < y)?y:x;
    }


И пример использования..
ExpandedWrap disabled
    float a = 123.76;
    double b = 123.04;
    float c = 125.15;
    int d;
    double e;
    d = MACROMAX(a, b);
    d = MACROMAX(a, c);
    e = templatemax(a, b);
    d = templatemax(a, c);


Цитата D_KEY @
Можно показать примеры кода? В каком контексте сравниваем-то?

См. выше. добавлю к первому посту :)

Что касается #define vs const, то это был один из следующих запланированных опросов... опережаете события!

Добавлено
Цитата JoeUser @
У меня есть хороший макро для целей анализа ... бета-версий, а-ля:

Кстати. Отличный пример :good:
char *out = "|*0>78-,+<|"; size_t cc = char_traits<char>::length(out);
for (size_t i=0;i<cc;i++)??<cout<<static_cast<char>((out??(i??)??'89));??>cout<<endl;


user posted image Чат Исходников в СкайпеЧат Исходников в Дискорде — Не проходим, а заходим!

user posted image
Нашел ту тему, там даже мои варианты были. Вот два из них:
Цитата D_KEY @

ExpandedWrap disabled
    int i = 0, j = 0, k = 0;
    restore(&i, &j, &k);
     
    for(; i < 10; ++i, j = i, k = j) {
      for (; j < 10; ++j, k = j) {
        for(; k < 10; ++k) {
     
          // ...
     
        }
      }
    }


Цитата D_KEY @
Есть еще вариант со switch :D
Не проверял, мог опечататься

ExpandedWrap disabled
    int i = 0, j = 0, k = 0;
    switch (restore(&i, &j, &k))
    case 0:
      for(i = 0; i < 10; ++i) {
        for (j = i; j < 10; ++j) {
          for(k = j; k < 10; ++k) {
    default:
             // ...
        
          }
        }
      }
    }



Сам я в той теме считал вариант с goto более понятным.
"If someone claims to have the perfect programming language, he is either a fool or a salesman or both"(c) Bjarne Stroustrup
Цитата KILLER @
Например из последнего, то что было с goto и я переписывал без goto:
Неприемлемо. Ты переписал пример на другом языке.
Всё написанное выше это всего лишь моё мнение, возможно ошибочное.
Цитата OpenGL @
И зачем разбивать? Функция с "первым же встретившится goto" предельно понятна.

Тебя может и не напрягают функции по тыще строчек, а меня напрягают.

Цитата OpenGL @
Начал переписывать, не поняв, какую проблему решает goto, очевидно :D

И какую проблему он там решает, какую не решает мой пример?

Цитата OpenGL @
Да ладно. Ну вот тебе ещё примеры из ядра линукса, git, quake 3. Дальше искать влом.

Ну я выше пример реализации raii и исключений привел на С, я там не нашел goto. И?

Цитата OpenGL @
Но, ты, конечно, можешь считать, что авторы всех этих программ - дебилы и говнокодеры, не догадавшиеся, что можно было просто обратиться к KILLER-у с исходников с вопросом "как переписать без goto" - я спорить с этим даже не буду :D

Даже K&R пишут что всегда можно обойтись без goto, и даже они считают что многие этим goto злоупотребляют. Т.е. по сути они согласны с моей точкой зрения. Но ведь они такие же дебилы видимо как и я? Все тру папки юзают goto ведь.

Цитата OpenGL @
О чём ты? Ты вполне себе ограничен - религиозной заморочкой "писать код без goto", которая, очевидно, мешает в определённых случаях писать более компакнтный и читаемый код :D

Ну собственно как и ты. Ты ведь раньше писал что тоже не используешь goto. А да, один раз на каком то делфи заюзал. Не мешает тебе это ограничение? Выходит мы с тобой оба ограничены? Или просто мыслим так, что в голову не приходит использование goto ? Как считаешь? Я еще раз повторюсь - я не сталкивался с задачами - где без goto нереально, либо мега сложно было бы реализовать что то. Возможно такие задачи есть, я с этим не спорю, я у вас просил их привести. Вы морозитесь, ну синтетические примеры с кучей ограничений разве что приводите.

Цитата OpenGL @
Перепиши. Вот зуб даю - если у тебя получится не хуже, чем с goto, то тебе тут не только я - половина участников темы плюсы поставит. От себя вообще три плюса обещаю :D

С теми ограничениями, которые ты придумал? Т.е. обязательно должен быть тройной цикл и обязательно нужно попасть внутрь этого тройного цикла минуя внешние? Даже и не буду пытаться насиловать себе мозг. Потому что считаю что эти ограничения несостоятельны. Убери ограничения, тогда будет время - попробую. Нам же важен конечный результат, а не как именно это будет реализовано?

Цитата OpenGL @
И что? Или ты не заметил, что тут решается задача "запрыгнуть внутрь циклов", и это не goto cleanup, смысла котоого в плюсах немного? :D

Конечно заметил. Я к тому, что это не кастрированный Си, где нет средств для реализации с помощью других технологий.
Цитата D_KEY @
даже если вы пишите на C, рассмотрите варианты с __finally для ms-компилятора и __attribute__ ((__cleanup__(f))) для gcc/clang.
Нестандартное расширение языка. Такие штуки допустимы в библиотеке компилятора, но крайне нежелательны в пользовательском коде. Мир С-компиляторов упомянутыми тремя компиляторами не ограничивается.
Сообщение отредактировано: amk -
Всё написанное выше это всего лишь моё мнение, возможно ошибочное.
Цитата amk @
Неприемлемо. Ты переписал пример на другом языке.

Майкрософт тоже писало ATL/MFC на другом языке. У них это приемлемо использовать goto в методе класса, а мне не приемлемо, странно как то :-?
Они могут многое себе позволить, хотя бы потому, что свою операционную систему собирают собственным компилятором. А вот ты пишешь программы для вообще говоря не совсем известного компилятора. Конечно, если ты ограничиваешься программированием для себя, ты можешь пользоваться любыми средствами.
Всё написанное выше это всего лишь моё мнение, возможно ошибочное.
Цитата amk @
Они могут многое себе позволить, хотя бы потому, что свою операционную систему собирают собственным компилятором.

То есть это сразу переводит уровень их кода из говнокода в код с хорошим стилем программирования? Странно :scratch:

Цитата amk @
А вот ты пишешь программы для вообще говоря не совсем известного компилятора. Конечно, если ты ограничиваешься программированием для себя, ты можешь пользоваться любыми средствами.

Для С++ сного вроде как. :-?
Цитата amk @
Нестандартное расширение языка. Такие штуки допустимы в библиотеке компилятора, но крайне нежелательны в пользовательском коде.

Очень много софта пишется под одну инфраструктуру.
В том же ядре линукса полно gcc-специфики. И это нормально. В nginx специфичные вещи обернуты. Можно пойти по такому пути.

Цитата
Мир С-компиляторов упомянутыми тремя компиляторами не ограничивается.

Нужно больше конкретики.

Кроме того, не забывай, что это лишь один из вариантов, что я предложил ;)
"If someone claims to have the perfect programming language, he is either a fool or a salesman or both"(c) Bjarne Stroustrup
Цитата KILLER @
Тебя может и не напрягают функции по тыще строчек, а меня напрягают.

Откуда "тыще"? Функция, о которой идёт речь, всего-то 150 строк занимает, включая комментарии, пустые строки и фигурные скобки, да и к тому же она простая как палка. Переписывание её на паттерн do..while просто зря добавит дополнительный нафиг не нужный отступ практически во всё тело функции.

Цитата KILLER @
И какую проблему он там решает, какую не решает мой пример?

Переход из цикла к cleanup, очевидно :D

Цитата KILLER @
Ну я выше пример реализации raii и исключений привел на С, я там не нашел goto. И?

А что "и"? Очевидно, что есть случаи, когда с goto читаемей и удобнее, а есть, когда и без него удобно всё делается. Твой пример, очевидно, из второй группы. Что ты им сказать хотел? :D

Цитата KILLER @
Даже K&R пишут что всегда можно обойтись без goto, и даже они считают что многие этим goto злоупотребляют. Т.е. по сути они согласны с моей точкой зрения.

:lool:
Киля, прикинь, у меня тоже есть эта книга. Вот цитата оттуда:
Цитата
В языке "C" предусмотрен и оператор GOTO, которым бесконечно злоупотребляют, и метки для ветвления. С формальной точки зрения оператор GOTO никогда не является необходимым, и на практике почти всегда можно обойтись без него. Мы не использовали GOTO в этой книге.
Тем не менее, мы укажем несколько ситуаций, где оператор GOTO может найти свое место.

Внимание, вопрос - ты утверждаешь, что приведённая цитата и твой опус
Цитата KILLER @
именно что самое по себе использование goto - зло.

эквивалентны? :crazy: А с тем, что всегда можно обойтись без goto, или что без него многие задачи могут быть решены ничуть не сложнее, никто и не спорит, поэтому зачем ты это усиленно пытаешься доказать - непонятно :D

Цитата KILLER @
Ну собственно как и ты. Ты ведь раньше писал что тоже не используешь goto. А да, один раз на каком то делфи заюзал.

Хм. :scratch: А можно я этот пост в рамочку и на стену отправлю - он доказывает, что ты изредка хоть что-то читать умеешь :D

Цитата KILLER @
Не мешает тебе это ограничение? Выходит мы с тобой оба ограничены?

А, нет, облом, ты не читатель :no-sad: Ну либо читатель, но не пониматель :no-sad: В чём заключается моё ограничение, если код с goto я написать могу, а ты - нет? :D

Цитата KILLER @
Вы морозитесь, ну синтетические примеры с кучей ограничений разве что приводите.

До-до-до, назови любой пример использования - синтетическим с кучей ограничений и дело в шляпе :jokingly:

Цитата KILLER @
С теми ограничениями, которые ты придумал? Т.е. обязательно должен быть тройной цикл и обязательно нужно попасть внутрь этого тройного цикла минуя внешние? Даже и не буду пытаться насиловать себе мозг. Потому что считаю что эти ограничения несостоятельны.

А, так ты не пишешь ничего сложнее helloworld-ов, раз не в состоянии представить, что задача в стиле "тройной цикл, есть возможность прервать в любом месте, и старт в случае прерывания - с того места, где произошла остановка" - вполне конкретная. Можно было это сказать сразу - тогда бы и срача на n страниц не было :D
И кстати, мне недавно как раз такую задачу и надо было решать - вычислить с указанными выше условиями значения некой функции f(x, y, z) для всех возможных входных параметров. Правда, писалось на языке без goto, так что пришлось городить огород с вычислением всех индексов руками. Писал бы на С/С++ - сделал бы goto и не парился. Это считается, что я юзал goto на практике? :D

Цитата KILLER @
Конечно заметил. Я к тому, что это не кастрированный Си, где нет средств для реализации с помощью других технологий.

Ога, и что характерно, на просьбу продемонстрировать решение задачи с их помощью ты сливаешься простым "ограничения несостоятельны" :lool:
Сообщение отредактировано: OpenGL -
Подпись была включена в связи с окончанием срока наказания
Я вот не помню случая, когда я бы использовал goto в проде.
Но конкретно в той задаче goto выглядит неплохо. Хотя в прод, думаю, что в любой команде, такое бы не заапрувили и пришли к какому-то другому варианту.
"If someone claims to have the perfect programming language, he is either a fool or a salesman or both"(c) Bjarne Stroustrup
Цитата D_KEY @
Я вот не помню случая, когда я бы использовал goto в проде.
Я тоже не помню. Но то, что пользовал, помню. :wacko: Как-то вот так вот. :-?
Одни с годами умнеют, другие становятся старше.
Цитата OpenGL @
Переход из цикла к cleanup, очевидно :D

Странно, а у меня его разве нету? :-? Вообще то у него не к клинапу переход, а переход за циклы, очистка памяти и выход из функции. В моем примере ровно то же самое. :-?

Цитата OpenGL @
Откуда "тыще"? Функция, о которой идёт речь, всего-то 150 строк занимает, включая комментарии, пустые строки и фигурные скобки, да и к тому же она простая как палка. Переписывание её на паттерн do..while просто зря добавит дополнительный нафиг не нужный отступ практически во всё тело функции.

Функция в 150 строк кода - тоже большая. И файл в 5 тыс строк большой. Попробуй проанализировать этот код глазами от начала до конца, не перематывая в конец. Не сможешь, либо тебе придется держать в уме с какого места ты прыгаешь. Потому что метку, которая находится в конце функции, и на которую прыгают в начале функции - глазами найти ты не сможешь. Тебе придется постоянно перематывать эту функцию туда обратно, чтоб понять логику. А без goto, ты сможешь прочитать не прыгая взад вперед по этой функции глазами.

Цитата OpenGL @
А что "и"? Очевидно, что есть случаи, когда с goto читаемей и удобнее, а есть, когда и без него удобно всё делается. Твой пример, очевидно, из второй группы. Что ты им сказать хотел? :D

Вы не привели таких случаев. Вы говорите о каких то мифических случаях, но приводите придуманные на коленке вилосипеды. Я так могу сказать - очевидно что есть случаи когда не нужно городить классов, и проектировать какие то наследования, паттерны и всякую хрень. Могу я этим аргументировать против ООП и все что с этим связано? Ведь смотри - зачем всякие эти стратегии, синглтоны, фасады, адаптеры, итераторы? Вот зачем все это городить? Ведь проще взять и писать в процедурном стиле. Вон в Си как то живут без всего этого и радуются. Нормально же. Но тем не менее на чуть более менее сложную системы - городят классы. Зачем? Если можно обойтись и функциями? Почему ты когда писал на Си не использовал такой мощный и очевидный инструмент как goto ? Может ты в Си с указателями не работал и память не выделял? Если не работал и не выделял память, значит ты на Си не писал. А если выделял - как же ты очищал ее без goto ?
Твоя проблема, да и остальных защитников - в том, что вы защищаете уже написанные примеры. Понимаешь?
Вот ты написал так, и тебе кажется что очевидно это круто. А на практике - это говнокод.

Потому что еще раз. Когда ты пишешь программу, которая состоит максимум из 100 строк - да пиши там хоть вообще без циклов на одних goto. С этим еще наверное можно как то разобраться. Но когда у тебя большой проект, и везде понапиханы goto - это говорит лишь об одном, ты плохо спроектировал свою систему, раз юзаешь goto для очистки памяти. И сопровождать такой код - тебе будет труднее.

Если мы говорим о велосипедах в 10 строчек, ок пусть там goto рулит. Хотя я всеравно его не использую, потому что мне нет необходимости его использовать. А если мы говорим не о велосипедах - то это значит, что ты нихрена не спроектировал, а просто написал в процедурном стиле там, где нужно было применять ООП. Вот и все. И доказываешь мне что тебе проще было написать в процедурном стиле, чем в ООП. Да написать тебе может было и проще. А понимать и сопровождать твой код - не проще.

Цитата OpenGL @
Киля, прикинь, у меня тоже есть эта книга. Вот цитата оттуда:

Ключевое слово там - может. А может и не найти. Часто ты прыгаешь из 4-ого по вложенности цикла(да даже из второго) в конец функции? Думаю что никогда, раз не юзаешь goto. И чего дальше? Почему ты не применяешь сам goto, но при этом за него топишь? Потому что рассматриваешь проблему с академической стороны, философствуешь. И хрен ты этот goto будешь использовать, останешься при своем. И ну что мне прикидывать?

Цитата OpenGL @
эквивалентны?

То есть ты сравниваешь предположение с утверждением и делаешь вывод что они эквиваленты?
Сырые указатели или неуправляемый код в Java/Шарпах - зло, но тем не менее иногда прибегают к их использованию. Исключения в деструкторах - зло в кубе, но тем не менее есть случаи когда приходится их там обрабатывать.

Цитата OpenGL @
А с тем, что всегда можно обойтись без goto, или что без него многие задачи могут быть решены ничуть не сложнее, никто и не спорит, поэтому зачем ты это усиленно пытаешься доказать - непонятно :D

Это не я доказываю. Это вы мне доказываете что приведенный код без goto переписать нереально или сложно или будет херово и некрасиво, и накладываете ограничения в виде - а у тебя тут другой язык, а у тебя тут нет прыжка именно вот отсюда, вон в туда. А у тебя не тройной цикл, а у тебя еще что то не то.

Цитата OpenGL @
Хм. :scratch: А можно я этот пост в рамочку и на стену отправлю - он доказывает, что ты изредка хоть что-то читать умеешь :D

Я посты все читаю всегда, внимательно. В отличии от вас. Я это уже говорил 100 раз. Где там я что забыл или не прочитал?

Цитата OpenGL @
А, нет, облом, ты не читатель :no-sad: Ну либо читатель, но не пониматель :no-sad: В чём заключается моё ограничение, если код с goto я написать могу, а ты - нет? :D

Твое ограничение заключается в том, что на словах ты Лев Толстой, а на деле, ну ты понял? Ты говоришь что можешь, но никогда не используешь. Ну и плюс ты не читатель. Потому что я тоже могу написать код с goto. И раньше я об этом писал. Один сел на жепу, когда я ему сказал что его пример не в тему. Хочешь тебя посажу, одной своей цитатой? Или ты сам найдешь?

Цитата OpenGL @
До-до-до, назови любой пример использования - синтетическим с кучей ограничений и дело в шляпе :jokingly:

А тут были какие то не синтетические примеры? Где? Покажи?

Цитата OpenGL @
А, так ты не пишешь ничего сложнее helloworld-ов, раз не в состоянии представить, что задача в стиле "тройной цикл, есть возможность прервать в любом месте, и старт в случае прерывания - с того места, где произошла остановка" - вполне конкретная. Можно было это сказать сразу - тогда бы и срача на n страниц не было :D

Я сложнее helloworl-ов, ничего никогда в жизни не писал. А еще могу сказать - что тройные циклы пишу ну очень редко. Еще с прошлой работы осталась привычка, что если вложенность цикла больше двух - значит код плохой, нужно бить на функции. И никак не могу от нее избавится представляешь? А чтоб прыгать внутрь тройного цикла или из тройного цикла на ружу, да еще с помощью goto - это вообще на моей практике пока такого не было.

Зачем мне прыгать из тройного цикла наружу с помощью goto? Ради самого факта прыжка? Сформулируй словами такую задачу, чтоб не оставалось выбора, как написать тройной цикл и сделать такой прыжок. Я подумаю. И если напишу ее с goto, то тогда наверное ты меня убедил и я пересмотрю свои взгляды на использование goto.

Ваши вопросы сродни - как ты будешь выходить из 10-ого по вложенности цикла сразу в конец функции. Но ответ вы в упор или не понимаете или не видите - я не пишу циклы с вложенностью 10.
10 - я намеренно тут написал, чтоб ты понял что с тремя циклами у меня работает примерно такая же логика. Хотя в принципе иногда и очень редко, когда мне лень разбивать на функции, и циклы маленькие я могу написать тройной цикл. Но по большому счету - это скорее исключение из правил, чем правило.

Цитата OpenGL @
И кстати, мне недавно как раз такую задачу и надо было решать - вычислить с указанными выше условиями значения некой функции f(x, y, z) для всех возможных входных параметров. Правда, писалось на языке без goto, так что пришлось городить огород с вычислением всех индексов руками. Писал бы на С/С++ - сделал бы goto и не парился. Это считается, что я юзал goto на практике? :D

Пфф, я же говорю "на словах я Лев Толстой, а на деле хрен простой". Вот когда будешь писать goto, тогда можешь бить себя пяткой в грудь и кричать что я применяю на практике goto.
Я тоже могу много чего написать.

Цитата OpenGL @
Ога, и что характерно, на просьбу продемонстрировать решение задачи с их помощью ты сливаешься простым "ограничения несостоятельны" :lool:

В каком смысле? Ты про пример Qraizer? Ну давай я подумаю на досуге, перепишу его и тебе покажу.
OpenGL, держи переписанный Qraizer'а код без goto. Я один раз проверил, особо не гонял. Если все гуд - жду от пол форума плюсов, плюс лично от тебя три штуки:
ExpandedWrap disabled
    #include <windows.h>
    #include <io.h>
    #include <conio.h>
    #include <fstream>
    #include <iostream>
     
    int main()
    {
        int i(0), j(0), k(0), l(0);
     
        std::ofstream log;
        log.open("file.log", std::ofstream::out | std::ofstream::trunc);
        std::clog.rdbuf(log.rdbuf());
     
        bool          mega_ok = true;
        if (_access("savedstate.dat", 4) == 0)     // Проверить, нет ли сохранённого состояния от предыдущего запуска
        {                                             // Если есть, восстановить и продолжиться
            std::ifstream inFile("savedstate.dat");
            
     
            mega_ok = mega_ok && inFile.read(reinterpret_cast<char*>(&i), sizeof(i)).gcount() == sizeof(i);
            mega_ok = mega_ok && inFile.read(reinterpret_cast<char*>(&j), sizeof(j)).gcount() == sizeof(j);
            mega_ok = mega_ok && inFile.read(reinterpret_cast<char*>(&k), sizeof(k)).gcount() == sizeof(k);
            mega_ok = mega_ok && inFile.read(reinterpret_cast<char*>(&l), sizeof(l)).gcount() == sizeof(l);
            if (mega_ok && (inFile.good() || inFile.eof()))
            {
                std::cout << "The saved state is successfully restored." << std::endl;
                //goto resume;
            }
            else return std::cerr << "The saved state restoring error. State file is wrong." << std::endl,
                1;
        }
     
        for ( !mega_ok ? i = 0 : i=i; i<10; ++i)
        {
            for (!mega_ok ? j = 0: j = i; j<10; ++j)
            {
                for (!mega_ok ? k = 0:k = j; k<10; ++k)
                {
                    for (!mega_ok ? l = 0:l = k; l<10; ++l)
                    {
                    //resume:
                        if (kbhit() && getch() == '\x1B')     // Проверить, не просят ли нас ESCпом прерваться
                        {                                     // Если да, сохранить состояние и выйти
                            if (_access("savedstate.dat", 2) == 0) remove("savedstate.dat"); //! <<<<<< Закоментируй чтобы начать с определенного состояния
     
                            std::ofstream outFile("savedstate.dat");
                            bool ok = true;
     
                            ok = ok && outFile.write(reinterpret_cast<char*>(&i), sizeof(i)).good();
                            ok = ok && outFile.write(reinterpret_cast<char*>(&j), sizeof(j)).good();
                            ok = ok && outFile.write(reinterpret_cast<char*>(&k), sizeof(k)).good();
                            ok = ok && outFile.write(reinterpret_cast<char*>(&l), sizeof(l)).good();
                            if (!(ok && (outFile.good() || outFile.eof())))
                                return std::cerr << "The state saving error." << std::endl,
                                1;
                            return std::cout << "The state successfully saved." << std::endl,
                                2;
                        }
     
                        /* ... */
     
                        std::clog << "i = " << i << ", j = " << j << ", k = " << k << ", l = " << l << std::endl;
                        Sleep(1);
                    }
                }
            }
        }
        std::cout << "Done... Pres any key...";
        std::cin.get();
        if (_access("savedstate.dat", 2) == 0) remove("savedstate.dat"); //! <<<<<< Закоментируй чтобы начать с определенного состояния
     
        
        std::clog.clear();
        log.close();
        return 0;
    }

Плюс код инициализирующий начальным состоянием файл savedstate.dat
ExpandedWrap disabled
        //! СОхраняем состояние всех счетчиков начиная с 3
        {
            int i(3), j(3), k(3), l(3);
            std::ofstream outFile("savedstate.dat");
            bool ok = true;
     
            ok = ok && outFile.write(reinterpret_cast<char*>(&i), sizeof(i)).good();
            ok = ok && outFile.write(reinterpret_cast<char*>(&j), sizeof(j)).good();
            ok = ok && outFile.write(reinterpret_cast<char*>(&k), sizeof(k)).good();
            ok = ok && outFile.write(reinterpret_cast<char*>(&l), sizeof(l)).good();
     
        }

Плюс, мержиловка онлайн тебе в помощь:
https://www.diffchecker.com
Сообщение отредактировано: KILLER -
Цитата KILLER @
Странно, а у меня его разве нету?

Твой пример - втупую переписанный код без осознания того, что это схема и, соответсвенно, того, в чём там реальная сложность, только и всего. И поскольку это уже было разжёвано не один раз, то я повторять смысла, что конкретно у тебя не так, не вижу - ты всё равно не поймёшь :D

Цитата KILLER @
Функция в 150 строк кода - тоже большая. И файл в 5 тыс строк большой. Попробуй проанализировать этот код глазами от начала до конца, не перематывая в конец. Не сможешь, либо тебе придется держать в уме с какого места ты прыгаешь. Потому что метку, которая находится в конце функции, и на которую прыгают в начале функции - глазами найти ты не сможешь. Тебе придется постоянно перематывать эту функцию туда обратно, чтоб понять логику. А без goto, ты сможешь прочитать не прыгая взад вперед по этой функции глазами.

Я - не неосилятор, как некоторые, и сразу понял, что делает обсуждаемая функция, равно как и понял логику её работы. Знал бы спецификацию http или семантику полей, в которые она пишет - понял бы полностью, вплоть до возможности не напрягаясь внести в неё изменения. ЧЯДНТ? :D

Цитата KILLER @
Почему ты когда писал на Си не использовал такой мощный и очевидный инструмент как goto ? Может ты в Си с указателями не работал и память не выделял? Если не работал и не выделял память, значит ты на Си не писал. А если выделял - как же ты очищал ее без goto ?

Потому что было не нужно :D На си я писал только пару олимпиадных задачек ради фана. Указатели там обычно используются так, как тебе даже в страшном сне не может присниться. А очищать память в этом случае просто нафиг не нужно - даже если её приходится выделять в куче, то проще забить на освобождение, ибо программа всё равно дольше пары секунд не проработает :crazy:

Цитата KILLER @
Ключевое слово там - может. А может и не найти.

Капитан, перелогинься :lool: Кто тут с этим спорит вообще? Ну да, может и не найти, и в этом случае лучше написать без goto. Но ведь может и найти - что тогда? :D

Цитата KILLER @
Часто ты прыгаешь из 4-ого по вложенности цикла(да даже из второго) в конец функции? Думаю что никогда, раз не юзаешь goto.

:lool:
Ты сам посчитаешь, сколько раз я говорил, что я не пишу на Си, поэтому самое частое применение goto - прыжок к очистке - мне не нужен, или это сделать мне? :D

Цитата KILLER @
Потому что еще раз. Когда ты пишешь программу, которая состоит максимум из 100 строк - да пиши там хоть вообще без циклов на одних goto. С этим еще наверное можно как то разобраться. Но когда у тебя большой проект, и везде понапиханы goto - это говорит лишь об одном, ты плохо спроектировал свою систему, раз юзаешь goto для очистки памяти. И сопровождать такой код - тебе будет труднее.

Внимание, вопрос - кто тут говорит, что надо писать программу, везде пихая goto? :D

Цитата KILLER @
Я посты все читаю всегда, внимательно. В отличии от вас. Я это уже говорил 100 раз. Где там я что забыл или не прочитал?

Да хоть вот тот пост, на который ты отвечаешь вот этой вот фразой - он явно показывает, что ты не прочитал, о чём идёт речь, иначе бы глупый вопрос - что ты забыл и не прочитал - ты бы не задавал. А глупый он потому, что в данной ветке дискуссии я не говорил, что ты что-то не прочитал, а даже наоборот - похвалил твою внимательность :crazy:

Цитата KILLER @
Еще с прошлой работы осталась привычка, что если вложенность цикла больше двух - значит код плохой, нужно бить на функции.

Вау. А венгерский алгоритм, алгоритм Флойда или вышеописанная мной задача, где я "использовал" goto - перебор всех аргументов в функции f(x, y, z) ты тоже будешь разбивать на функции? :crazy:

Цитата KILLER @
Твое ограничение заключается в том, что на словах ты Лев Толстой, а на деле, ну ты понял? Ты говоришь что можешь, но никогда не используешь.

А что такого? Я считаю, что юзать goto там, где он к месту - нормально. Можно даже усилить - юзать %something% там, где оно к месту - нормально. Ну а почему я сам это не делаю - на это может быть тысяча причин. Или ты делаешь всё, что считаешь нормальным? :crazy:

Цитата KILLER @
Потому что я тоже могу написать код с goto. И раньше я об этом писал. Один сел на жепу, когда я ему сказал что его пример не в тему. Хочешь тебя посажу, одной своей цитатой? Или ты сам найдешь?

Я в курсе, что ты это говорил, но поскольку ты старательно пытаешься доказать, что goto, когда оно в тему, на самом деле всё ухудшает - я просто записал эту твою фразу в обычное балабольство :D
Подпись была включена в связи с окончанием срока наказания
OpenGL, и там посмотри, я забыл переменные инициализировать, я поправил. Хрен его знает - вроде делает вид что работает, но я толком не тестил.
Цитата KILLER @
OpenGL, держи переписанный Qraizer'а код без goto.

Фиаско. У тебя, если ты дошёл до цикла, mega_ok всегда равно true. Как следствие, инициализация счётчиков цикла у тебя всегда будет идти по ветке false, т.е. ровно так, как в исходном цикле, если бы мы зашли в него как обычно. Иными словами - вне зависимости от того, что ты восстановил, ты пойдёшь крутиться в циклах с самого начала :)
Подпись была включена в связи с окончанием срока наказания
Цитата OpenGL @
У тебя, если ты дошёл до цикла, mega_ok всегда равно true

С чего вдруг?
Цитата OpenGL @
Иными словами - вне зависимости от того, что ты восстановил, ты пойдёшь крутиться в циклах с самого начала

А, не, вру - не с самого начала. Мои поздравления - переменную i ты восстановил. Осталось восстановить ещё три оставшихся переменных :D

Добавлено
Цитата KILLER @
С чего вдруг?

ExpandedWrap disabled
        bool          mega_ok = true;
        if (_access("savedstate.dat", 4) == 0)     // Проверить, нет ли сохранённого состояния от предыдущего запуска
        {                                             // Если есть, восстановить и продолжиться
            std::ifstream inFile("savedstate.dat");
            
     
            mega_ok = mega_ok && inFile.read(reinterpret_cast<char*>(&i), sizeof(i)).gcount() == sizeof(i);
            mega_ok = mega_ok && inFile.read(reinterpret_cast<char*>(&j), sizeof(j)).gcount() == sizeof(j);
            mega_ok = mega_ok && inFile.read(reinterpret_cast<char*>(&k), sizeof(k)).gcount() == sizeof(k);
            mega_ok = mega_ok && inFile.read(reinterpret_cast<char*>(&l), sizeof(l)).gcount() == sizeof(l);
            if (mega_ok && (inFile.good() || inFile.eof()))
            {
                std::cout << "The saved state is successfully restored." << std::endl;
                //goto resume;
            }
            else return std::cerr << "The saved state restoring error. State file is wrong." << std::endl,
                1;
        }

1) До условия mega_ok всегда true.
2) Мы зашли в условие. Если mega_ok в нём поменялась на false - внутреннее условие у тебя уйдёт в return и до цикла не дойдёт.
3) Поскольку в других частях кода присваиваний mega_ok нет, то вышеозвученный вывод - что mega_ok всегда true - верен.
Сообщение отредактировано: OpenGL -
Подпись была включена в связи с окончанием срока наказания
Цитата OpenGL @
Как следствие, инициализация счётчиков цикла у тебя всегда будет идти по ветке false, т.е. ровно так, как в исходном цикле, если бы мы зашли в него как обычно. Иными словами - вне зависимости от того, что ты восстановил, ты пойдёшь крутиться в циклах с самого начала :)

Вот лог - когда для всех счетчиков в файле savedstate.dat записано 3:
Цитата
i = 3, j = 3, k = 3, l = 3
i = 3, j = 3, k = 3, l = 4
i = 3, j = 3, k = 3, l = 5
i = 3, j = 3, k = 3, l = 6
i = 3, j = 3, k = 3, l = 7
i = 3, j = 3, k = 3, l = 8
i = 3, j = 3, k = 3, l = 9
i = 3, j = 3, k = 4, l = 4
i = 3, j = 3, k = 4, l = 5
i = 3, j = 3, k = 4, l = 6
i = 3, j = 3, k = 4, l = 7
i = 3, j = 3, k = 4, l = 8
i = 3, j = 3, k = 4, l = 9
i = 3, j = 3, k = 5, l = 5
i = 3, j = 3, k = 5, l = 6
i = 3, j = 3, k = 5, l = 7
i = 3, j = 3, k = 5, l = 8
i = 3, j = 3, k = 5, l = 9
i = 3, j = 3, k = 6, l = 6
i = 3, j = 3, k = 6, l = 7
i = 3, j = 3, k = 6, l = 8
i = 3, j = 3, k = 6, l = 9
i = 3, j = 3, k = 7, l = 7
i = 3, j = 3, k = 7, l = 8
i = 3, j = 3, k = 7, l = 9
i = 3, j = 3, k = 8, l = 8
i = 3, j = 3, k = 8, l = 9
i = 3, j = 3, k = 9, l = 9
i = 3, j = 4, k = 4, l = 4
i = 3, j = 4, k = 4, l = 5
i = 3, j = 4, k = 4, l = 6
i = 3, j = 4, k = 4, l = 7
i = 3, j = 4, k = 4, l = 8
i = 3, j = 4, k = 4, l = 9
i = 3, j = 4, k = 5, l = 5
i = 3, j = 4, k = 5, l = 6
i = 3, j = 4, k = 5, l = 7
i = 3, j = 4, k = 5, l = 8
i = 3, j = 4, k = 5, l = 9
i = 3, j = 4, k = 6, l = 6
i = 3, j = 4, k = 6, l = 7
i = 3, j = 4, k = 6, l = 8
i = 3, j = 4, k = 6, l = 9
i = 3, j = 4, k = 7, l = 7
i = 3, j = 4, k = 7, l = 8
i = 3, j = 4, k = 7, l = 9
i = 3, j = 4, k = 8, l = 8
i = 3, j = 4, k = 8, l = 9
i = 3, j = 4, k = 9, l = 9
i = 3, j = 5, k = 5, l = 5
i = 3, j = 5, k = 5, l = 6
i = 3, j = 5, k = 5, l = 7
i = 3, j = 5, k = 5, l = 8
i = 3, j = 5, k = 5, l = 9
i = 3, j = 5, k = 6, l = 6
i = 3, j = 5, k = 6, l = 7
i = 3, j = 5, k = 6, l = 8
i = 3, j = 5, k = 6, l = 9
i = 3, j = 5, k = 7, l = 7
i = 3, j = 5, k = 7, l = 8
i = 3, j = 5, k = 7, l = 9
i = 3, j = 5, k = 8, l = 8
i = 3, j = 5, k = 8, l = 9
i = 3, j = 5, k = 9, l = 9
i = 3, j = 6, k = 6, l = 6
i = 3, j = 6, k = 6, l = 7
i = 3, j = 6, k = 6, l = 8
i = 3, j = 6, k = 6, l = 9
i = 3, j = 6, k = 7, l = 7
i = 3, j = 6, k = 7, l = 8
i = 3, j = 6, k = 7, l = 9
i = 3, j = 6, k = 8, l = 8
i = 3, j = 6, k = 8, l = 9
i = 3, j = 6, k = 9, l = 9
i = 3, j = 7, k = 7, l = 7
i = 3, j = 7, k = 7, l = 8
i = 3, j = 7, k = 7, l = 9
i = 3, j = 7, k = 8, l = 8
i = 3, j = 7, k = 8, l = 9
i = 3, j = 7, k = 9, l = 9
i = 3, j = 8, k = 8, l = 8
i = 3, j = 8, k = 8, l = 9
i = 3, j = 8, k = 9, l = 9
i = 3, j = 9, k = 9, l = 9
i = 4, j = 4, k = 4, l = 4
i = 4, j = 4, k = 4, l = 5
i = 4, j = 4, k = 4, l = 6
i = 4, j = 4, k = 4, l = 7
i = 4, j = 4, k = 4, l = 8
i = 4, j = 4, k = 4, l = 9
i = 4, j = 4, k = 5, l = 5
i = 4, j = 4, k = 5, l = 6
i = 4, j = 4, k = 5, l = 7
i = 4, j = 4, k = 5, l = 8
i = 4, j = 4, k = 5, l = 9
i = 4, j = 4, k = 6, l = 6
i = 4, j = 4, k = 6, l = 7
i = 4, j = 4, k = 6, l = 8
i = 4, j = 4, k = 6, l = 9
i = 4, j = 4, k = 7, l = 7
i = 4, j = 4, k = 7, l = 8
i = 4, j = 4, k = 7, l = 9
i = 4, j = 4, k = 8, l = 8
i = 4, j = 4, k = 8, l = 9
i = 4, j = 4, k = 9, l = 9
i = 4, j = 5, k = 5, l = 5
i = 4, j = 5, k = 5, l = 6
i = 4, j = 5, k = 5, l = 7
i = 4, j = 5, k = 5, l = 8
i = 4, j = 5, k = 5, l = 9
i = 4, j = 5, k = 6, l = 6
i = 4, j = 5, k = 6, l = 7
i = 4, j = 5, k = 6, l = 8
i = 4, j = 5, k = 6, l = 9
i = 4, j = 5, k = 7, l = 7
i = 4, j = 5, k = 7, l = 8
i = 4, j = 5, k = 7, l = 9
i = 4, j = 5, k = 8, l = 8
i = 4, j = 5, k = 8, l = 9
i = 4, j = 5, k = 9, l = 9
i = 4, j = 6, k = 6, l = 6
i = 4, j = 6, k = 6, l = 7
i = 4, j = 6, k = 6, l = 8
i = 4, j = 6, k = 6, l = 9
i = 4, j = 6, k = 7, l = 7
i = 4, j = 6, k = 7, l = 8
i = 4, j = 6, k = 7, l = 9
i = 4, j = 6, k = 8, l = 8
i = 4, j = 6, k = 8, l = 9
i = 4, j = 6, k = 9, l = 9
i = 4, j = 7, k = 7, l = 7
i = 4, j = 7, k = 7, l = 8
i = 4, j = 7, k = 7, l = 9
i = 4, j = 7, k = 8, l = 8
i = 4, j = 7, k = 8, l = 9
i = 4, j = 7, k = 9, l = 9
i = 4, j = 8, k = 8, l = 8
i = 4, j = 8, k = 8, l = 9
i = 4, j = 8, k = 9, l = 9
i = 4, j = 9, k = 9, l = 9
i = 5, j = 5, k = 5, l = 5
i = 5, j = 5, k = 5, l = 6
i = 5, j = 5, k = 5, l = 7
i = 5, j = 5, k = 5, l = 8
i = 5, j = 5, k = 5, l = 9
i = 5, j = 5, k = 6, l = 6
i = 5, j = 5, k = 6, l = 7
i = 5, j = 5, k = 6, l = 8
i = 5, j = 5, k = 6, l = 9
i = 5, j = 5, k = 7, l = 7
i = 5, j = 5, k = 7, l = 8
i = 5, j = 5, k = 7, l = 9
i = 5, j = 5, k = 8, l = 8
i = 5, j = 5, k = 8, l = 9
i = 5, j = 5, k = 9, l = 9
i = 5, j = 6, k = 6, l = 6
i = 5, j = 6, k = 6, l = 7
i = 5, j = 6, k = 6, l = 8
i = 5, j = 6, k = 6, l = 9
i = 5, j = 6, k = 7, l = 7
i = 5, j = 6, k = 7, l = 8
i = 5, j = 6, k = 7, l = 9
i = 5, j = 6, k = 8, l = 8
i = 5, j = 6, k = 8, l = 9
i = 5, j = 6, k = 9, l = 9
i = 5, j = 7, k = 7, l = 7
i = 5, j = 7, k = 7, l = 8
i = 5, j = 7, k = 7, l = 9
i = 5, j = 7, k = 8, l = 8
i = 5, j = 7, k = 8, l = 9
i = 5, j = 7, k = 9, l = 9
i = 5, j = 8, k = 8, l = 8
i = 5, j = 8, k = 8, l = 9
i = 5, j = 8, k = 9, l = 9
i = 5, j = 9, k = 9, l = 9
i = 6, j = 6, k = 6, l = 6
i = 6, j = 6, k = 6, l = 7
i = 6, j = 6, k = 6, l = 8
i = 6, j = 6, k = 6, l = 9
i = 6, j = 6, k = 7, l = 7
i = 6, j = 6, k = 7, l = 8
i = 6, j = 6, k = 7, l = 9
i = 6, j = 6, k = 8, l = 8
i = 6, j = 6, k = 8, l = 9
i = 6, j = 6, k = 9, l = 9
i = 6, j = 7, k = 7, l = 7
i = 6, j = 7, k = 7, l = 8
i = 6, j = 7, k = 7, l = 9
i = 6, j = 7, k = 8, l = 8
i = 6, j = 7, k = 8, l = 9
i = 6, j = 7, k = 9, l = 9
i = 6, j = 8, k = 8, l = 8
i = 6, j = 8, k = 8, l = 9
i = 6, j = 8, k = 9, l = 9
i = 6, j = 9, k = 9, l = 9
i = 7, j = 7, k = 7, l = 7
i = 7, j = 7, k = 7, l = 8
i = 7, j = 7, k = 7, l = 9
i = 7, j = 7, k = 8, l = 8
i = 7, j = 7, k = 8, l = 9
i = 7, j = 7, k = 9, l = 9
i = 7, j = 8, k = 8, l = 8
i = 7, j = 8, k = 8, l = 9
i = 7, j = 8, k = 9, l = 9
i = 7, j = 9, k = 9, l = 9
i = 8, j = 8, k = 8, l = 8
i = 8, j = 8, k = 8, l = 9
i = 8, j = 8, k = 9, l = 9
i = 8, j = 9, k = 9, l = 9
i = 9, j = 9, k = 9, l = 9


Добавлено
Цитата OpenGL @
А, не, вру - не с самого начала. Мои поздравления - переменную i ты восстановил. Осталось восстановить ещё три оставшихся переменных :D

Короче, может хватить гадать? Давай ты мне скажешь что мне нужно сделать, что бы получить неверные данные, а не будешь говорить что у меня там происходит, даже не запустив программу? Я запускал без файла и сохранненного состояния, полученные данные кидал в мержиловку - все ок.
Потом сохранял состояния и запускал, полученные данные сравнивал с исходными.
Напиши сценарий что мне нужно сделать что бы получить не валидные данные? Я хз как тестить, чтоб получить то, что тыговоришь?
Цитата KILLER @

Короче, может хватить гадать? Давай ты мне скажешь что мне нужно сделать, что бы получить неверные данные, а не будешь говорить что у меня там происходит, даже не запустив программу? Я запускал без файла и сохранненного состояния, полученные данные кидал в мержиловку - все ок.

Запусти с состояния, где все переменные различны.
Подпись была включена в связи с окончанием срока наказания
Цитата OpenGL @
Фиаско. У тебя, если ты дошёл до цикла, mega_ok всегда равно true.
Та не. Просто въехать в архитектуру коды втрое сложнее, и работает оно вдвое медленнее. А так нормально, этот вариант тоже приводился.
Одни с годами умнеют, другие становятся старше.
Цитата OpenGL @
1) До условия mega_ok всегда true.
2) Мы зашли в условие. Если mega_ok в нём поменялась на false - внутреннее условие у тебя уйдёт в return и до цикла не дойдёт.
3) Поскольку в других частях кода присваиваний mega_ok нет, то вышеозвученный вывод - что mega_ok всегда true - верен.

То есть выпадет в ошибку? Так это притензии к Qraizery, а не ко мне, я этот код не трогал. Я там только название переменной изменил, чтоб не было конфликта имен.

Добавлено
Цитата OpenGL @
Запусти с состояния, где все переменные различны.

Ну ок, щас сохраню их.
Правда, работает неправильно.
Одни с годами умнеют, другие становятся старше.
Цитата Qraizer @
Та не. Просто въехать в архитектуру коды втрое сложнее, и работает оно вдвое медленнее. А так нормально, этот вариант тоже приводился.

Я выше объяснил, почему в его коде смысла в mega_ok нет никакого. Я понимаю, что он хочет сделать, и да - вердикт этому коду ты уже озвучил.
Подпись была включена в связи с окончанием срока наказания
А кто-нибудь помнит, как вы от define и template перешли к goto и весёлым конкурсам по написанию говнокода?
"If someone claims to have the perfect programming language, he is either a fool or a salesman or both"(c) Bjarne Stroustrup
А вообще, по-моему замечательная демонстрация. Код переписан без goto, ещё не работает, но уже непонятен - я не сразу понял, что именно там не работает :lool:
Подпись была включена в связи с окончанием срока наказания
Короче, предлагаю перенесли полемику о goto в подобающую ему тему. Эта как бы о другом. Не то я счас скажу, что "рекурсия – это говнокод".

Добавлено
Ой, сказал :blush:
Сообщение отредактировано: Qraizer -
Одни с годами умнеют, другие становятся старше.
KILLER, видел? Можешь ещё по той теме погулять, там и код был и срач(с твоим участием тоже)

Цитата D_KEY @
Нашел ту тему, там даже мои варианты были. Вот два из них:
Цитата D_KEY @

ExpandedWrap disabled
    int i = 0, j = 0, k = 0;
    restore(&i, &j, &k);
     
    for(; i < 10; ++i, j = i, k = j) {
      for (; j < 10; ++j, k = j) {
        for(; k < 10; ++k) {
     
          // ...
     
        }
      }
    }


Цитата D_KEY @
Есть еще вариант со switch :D
Не проверял, мог опечататься

ExpandedWrap disabled
    int i = 0, j = 0, k = 0;
    switch (restore(&i, &j, &k))
    case 0:
      for(i = 0; i < 10; ++i) {
        for (j = i; j < 10; ++j) {
          for(k = j; k < 10; ++k) {
    default:
             // ...
        
          }
        }
      }
    }



Сам я в той теме считал вариант с goto более понятным.
"If someone claims to have the perfect programming language, he is either a fool or a salesman or both"(c) Bjarne Stroustrup
Цитата D_KEY @
А кто-нибудь помнит, как вы от define и template перешли к goto и весёлым конкурсам по написанию говнокода?

Это всё я :crazy: Мне стало интересно - действительно ли у них в примерах и SDK много goto, и я попросил пруфов. А потом внезапно всё заверте... :D
Подпись была включена в связи с окончанием срока наказания
Цитата OpenGL @
Запусти с состояния, где все переменные различны.

Вот состояния переменных в файле:
// int i(3), j(4), k(5), l(6);

Результаты идентичны. Скажи конкретные цифры, какие нужно задать, чтоб не работало?

Добавлено
Цитата OpenGL @
Код переписан без goto, ещё не работает, но уже непонятен - я не сразу понял, что именно там не работает :lool:

А что именно не работает? Я просто реально понять не могу :-?

Цитата Qraizer @
Правда, работает неправильно.

Qraizer, ну хоть ты объясни где не правильно? Результаты выдает идентичные, я сравниваю их в мержиловке, на которую кинул ссылку.

Добавлено
Цитата Qraizer @
Не то я счас скажу, что "рекурсия – это говнокод".

Нет, не согласен. Иногда здорово выручает и облегчает жизнь. Хотя уйти в стековерфлоу да, легко можно, если что то проглядеть.

Добавлено
Цитата OpenGL @
Я выше объяснил, почему в его коде смысла в mega_ok нет никакого. Я понимаю, что он хочет сделать, и да - вердикт этому коду ты уже озвучил.

Это всего лишь твои домыслы, причем пока не подтвержденные. И какой вердикт этому коду? С goto - ой какой красивый код, ну супер просто, с тернарным оператором - вердикт коду - говно? Так мне лень было вообще все переписывать и перепроектировать, я пошел по самому простому пути, оставить все как есть, и убрать только goto.
Цитата KILLER @
Результаты идентичны. Скажи конкретные цифры, какие нужно задать, чтоб не работало?

Собственно, на 3, 4, 5, 6 оригинальный код должен стартануть с них, а твой - с 3, 3, 3, 3. Если же у тебя разницы нет, то либо ты скопипастил сюда другой код, либо не тот вывод в дифвьювер.
Подпись была включена в связи с окончанием срока наказания
Цитата OpenGL @
Собственно, на 3, 4, 5, 6 оригинальный код должен стартануть с них, а твой - с 3, 3, 3, 3. Если же у тебя разницы нет, то либо ты скопипастил сюда другой код, либо не тот вывод в дифвьювер.

Да, точно. Видимо при раскоментировании блока, случайно расскоментировался goto. Ладно, подумаю потом еще.
А почему просто не завести классик для "позиции" с каким-то next и is_done(или вообще полноценные итераторы/диапазоны)? Мне кажется, что в реальном проде что-то такое и было бы...
"If someone claims to have the perfect programming language, he is either a fool or a salesman or both"(c) Bjarne Stroustrup
На предмет goto в библиотеках MS.
Исключения полноценно стали поддерживаться только в VC4.2, который увидел свет в 1998-ом, незадолго до VC6. До этого компилятор их понимал очень ограничено, а до версии 4.0 (вроде бы) не понимал вообще. Библиотека MFC увидела свет в ...1992-ом, ещё на 16-битном Microsoft Quick C for Windows. Соответственно потому в MFC есть собственные exception-макросы. ATL разрабатывалась попозже, но не сильно. Первые версии вошли в, если не ошибаюсь, тот же VC4.2. Соответственно использование там C++EH было, наверное возможным, но были, видать, причины не раскачивать лодку. Тем более, что совмещение SEH с C++EH в пределах одной программы всё-таки и сегодня иногда вызывает определённые сложности.
Одни с годами умнеют, другие становятся старше.
Цитата D_KEY @
А почему просто не завести классик для "позиции" с каким-то next и is_done(или вообще полноценные итераторы/диапазоны)? Мне кажется, что в реальном проде что-то такое и было бы...

Потому что тут идет переписывание уже существующего, готового кода, а не написание с нуля :rolleyes:

Добавлено
Я родил еще одно решение, возможно правильное, по крайней мере для разных сохраненных состояний выдает вроде верный резхультат:
ExpandedWrap disabled
    #include <windows.h>
    #include <io.h>
    #include <conio.h>
    #include <fstream>
    #include <iostream>
     
    int SaveStateToFile(int i, int j, int k, int l)
    {
        std::ofstream outFile("savedstate.dat");
        bool ok = true;
     
        ok = ok && outFile.write(reinterpret_cast<char*>(&i), sizeof(i)).good();
        ok = ok && outFile.write(reinterpret_cast<char*>(&j), sizeof(j)).good();
        ok = ok && outFile.write(reinterpret_cast<char*>(&k), sizeof(k)).good();
        ok = ok && outFile.write(reinterpret_cast<char*>(&l), sizeof(l)).good();
        if (!(ok && (outFile.good() || outFile.eof())))
            return std::cerr << "The state saving error." << std::endl, 1;
        return std::cout << "The state successfully saved." << std::endl, 2;
    }
     
    int main()
    {
        int itI, itJ, itK, itL;
        int savedI, savedJ, savedK, savedL;
        std::ofstream log;
        log.open("file.log", std::ofstream::out | std::ofstream::trunc);
        std::clog.rdbuf(log.rdbuf());
     
        bool          mega_ok = false;
        if (_access("savedstate.dat", 4) == 0)     // Проверить, нет ли сохранённого состояния от предыдущего запуска
        {                                             // Если есть, восстановить и продолжиться
            std::ifstream inFile("savedstate.dat");
            mega_ok = inFile.read(reinterpret_cast<char*>(&savedI), sizeof(savedI)).gcount() == sizeof(savedI);
            mega_ok &= inFile.read(reinterpret_cast<char*>(&savedJ), sizeof(savedJ)).gcount() == sizeof(savedJ);
            mega_ok &= inFile.read(reinterpret_cast<char*>(&savedK), sizeof(savedK)).gcount() == sizeof(savedK);
            mega_ok &= inFile.read(reinterpret_cast<char*>(&savedL), sizeof(savedL)).gcount() == sizeof(savedL);
            if (mega_ok && (inFile.good() || inFile.eof()))
            {
                std::cout << "The saved state is successfully restored." << std::endl;
                //goto resume;
            }
            else return std::cerr << "The saved state restoring error. State file is wrong." << std::endl,
                1;
        }
     
        for (itI = 0; itI<10; ++itI)
        {
            for (itJ = itI; itJ<10; ++itJ)
            {
                for (itK = itJ; itK<10; ++itK)
                {
                    for (itL = itK; itL<10; ++itL)
                    {
                        if (mega_ok) //! Если файл был прочитан, востанавливаем значения из файла 1 раз.
                        {
                            itI = savedI;
                            itJ = savedJ;
                            itK = savedK;
                            itL = savedL;
                            mega_ok = false;
                        }
     
                        if (kbhit() && getch() == '\x1B')     // Проверить, не просят ли нас ESCпом прерваться
                        {                                     // Если да, сохранить состояние и выйти
                            //if (_access("savedstate.dat", 2) == 0) remove("savedstate.dat"); //! <<<<<< Закоментируй чтобы начать с определенного состояния
     
                            return SaveStateToFile(itI, itJ, itK, itL);
                        }
                                                              
                        std::clog << "i = " << itI << ", j = " << itJ << ", k = " << itK << ", l = " << itL<< std::endl;
                        Sleep(1);
                    }
                }
            }
        }
     
        std::cout << "Done... Pres any key...";
        std::cin.get();
    //  if (_access("savedstate.dat", 2) == 0) remove("savedstate.dat"); //! <<<<<< Закоментируй чтобы начать с определенного состояния
     
     
        std::clog.flush();
        return 0;
    }


Добавлено
Что скажете? Вроде как похоже на рабочее. Т.е. после того как мы читаем файл - мы не прыгаем внутрь циклов. Мы после вхождения в самый вложенный цикл просто проверяем - если данные из файла прочитаны, то мы ими инициализируем итераторы, и ставим флаг в состояние ложь(файл не прочитан), и все начинается крутится с этих значений. Если файл не прочитан - пройдет инициализация в циклах.

Добавлено
Для удобства чтения убрал сохранение состояния в отдельную функцию, оно только реально запутывает.
Сообщение отредактировано: KILLER -
Ну вот все спать ушились, а у меня голова забита этим гребаным алгоритмом, и мыслей куча. Что теперь деать?
Цитата KILLER @
Цитата D_KEY @
А почему просто не завести классик для "позиции" с каким-то next и is_done(или вообще полноценные итераторы/диапазоны)? Мне кажется, что в реальном проде что-то такое и было бы...

Потому что тут идет переписывание уже существующего, готового кода, а не написание с нуля :rolleyes:

Это больше к Qraizer'у вопрос.
"If someone claims to have the perfect programming language, he is either a fool or a salesman or both"(c) Bjarne Stroustrup
Цитата D_KEY @
А почему просто не завести классик для "позиции" с каким-то next и is_done(или вообще полноценные итераторы/диапазоны)? Мне кажется, что в реальном проде что-то такое и было бы...

Я так и сделал в своей этой задаче. next получился примерно таким:
ExpandedWrap disabled
    bool next()
    {
        int *a[n] = {&i, &j, &k, &l};
        int c = n - 1;
        while(c >= 0 && *a[c] == 10) --c;
        if(c < 0) return false;
        while(c < n)
        {
            ++c;
            *a[c] = *a[c - 1];
        }
        return true;
    }

Куда менее читаемо - порядок обхода сразу и не ясен.

Цитата KILLER @
Что скажете?

Весьма неплохо, кстати. Я бы даже сказал, что вполне приемлемо - проследить логику тут сложнее, чем с goto, но проще, чем в вариантах, предлагаемых в той теме. Плюс по-моему вполне заслужил :yes:
Подпись была включена в связи с окончанием срока наказания
Цитата KILLER @
Что теперь деать?

Ну и заводной ты чел, Киля :lol:
У меня тож нечто похожее получилось без прыжков. Но оверхед на проверках явный.

ExpandedWrap disabled
    #include <iostream>
    #include <fstream>
     
    using namespace std;
     
    void FuncSave(const int a, const int b, const int c) {
      ofstream f("saved.txt");
      f << a << "\n" << b << "\n" << c;
    }
     
    bool FuncRestore(int& a, int& b, int& c) {
      a = 0; b = 0; c = 0;
      ifstream f("saved.txt");
      if (!f.good()) return false;
      cout << "Восстанавливаемся и продолжаем ..." << endl;
      f >> a >> b >> c;
      return true;
    }
     
    int main() {
      int i,j,k;
      bool r = FuncRestore(i,j,k);
      for(i = (r) ? i:0; i<5; i++) {
        for(j = (r) ? j:i; j<5; j++) {
          for(k = (r) ? k:j; k<5; k++) {
            if (r) { r = false; continue; }
            // делаем важное дело
            cout << i << ":" << j << ":" << k << endl;
            // эмуляция прерывания
            if (i==2 && j==2 && k==2) {
              cout << "Прервемся на 2:2:2 и сохраняемся" << endl;
              FuncSave(i,j,k);
              return 0;
            }
          }
        }
      }
      return 0;
    }


Вывод после двух запусков вот такой:
Скрытый текст
ExpandedWrap disabled
    0:0:0
    0:0:1
    0:0:2
    0:0:3
    0:0:4
    0:1:1
    0:1:2
    0:1:3
    0:1:4
    0:2:2
    0:2:3
    0:2:4
    0:3:3
    0:3:4
    0:4:4
    1:1:1
    1:1:2
    1:1:3
    1:1:4
    1:2:2
    1:2:3
    1:2:4
    1:3:3
    1:3:4
    1:4:4
    2:2:2
    Прервемся на 2:2:2 и сохраняемся
    Для закрытия данного окна нажмите <ВВОД>...
     
    Восстанавливаемся и продолжаем ...
    2:2:3
    2:2:4
    2:3:3
    2:3:4
    2:4:4
    3:3:3
    3:3:4
    3:4:4
    4:4:4
    Для закрытия данного окна нажмите <ВВОД>...
Мои программные ништякиhttp://majestio.info
Цитата KILLER @
Что скажете?

Думаю, что для прода этот вариант лучше, чем с goto :)
Но на работе я бы вообще сделал шаг назад и посмотрел на другие варианты решения вцелом.

Добавлено
Цитата OpenGL @
Куда менее читаемо - порядок обхода сразу и не ясен.

Зато с использованием уже проблем не будет, там будет ясно, что и зачем делается. А над этим куском, отвечающим за переход к следующему, можно дальше подумать. В итоге лапши меньше.
"If someone claims to have the perfect programming language, he is either a fool or a salesman or both"(c) Bjarne Stroustrup
Цитата OpenGL @
Твой пример - втупую переписанный код без осознания того, что это схема и, соответсвенно, того, в чём там реальная сложность, только и всего. И поскольку это уже было разжёвано не один раз, то я повторять смысла, что конкретно у тебя не так, не вижу - ты всё равно не поймёшь :D

Слушай, а хорошую ты позицию занял, выдумал какую то хрень, и топишь за нее. cppasm почему то не догадался придраться к тому, к чему придрался ты. Он наверное просто хуже тебя знает что он сам и писал? Или ты за него додумал и привел аргумент? Чтоб та программа работала как говоришь ты, необходимо было вставить после цикла хотя бы три точки. Чтобы было ясно - что между циклом и выходом есть еще код. В противном случае ты не имеешь никакого морального права упрекать меня в том, что мой пример не соответствует его примеру. Приводи свой пример, как ты расписываешь, я перепишу его, если будет время. А то сначало привели какую то шнягу, вам ее переписали, а потом вы меняете условие задачи, чтоб обвинить меня в том, что мой пример не работает? Не по людски получается как то. Я не телепат что бы догадываться что он там хотел написать. И где гарантии что ты еще щас что то не придумаешь, может у него там еще одна метка есть, за циклом, которая перемещает нас обратно внутрь цикла, ну это же очевидно, просто ты ее не видешь, так как не понимаешь логику программы. Да?

Цитата OpenGL @
Я - не неосилятор, как некоторые, и сразу понял, что делает обсуждаемая функция, равно как и понял логику её работы. Знал бы спецификацию http или семантику полей, в которые она пишет - понял бы полностью, вплоть до возможности не напрягаясь внести в неё изменения. ЧЯДНТ? :D

А я неосилятор, даже смотреть ее не стал. Я просто кинул взгляд и сразу понял - это трешь. Хорошо написанный код - я бы понял сразу, просто кинув взгляд(за исключением алгоритмов и разных вычислений). Тут нужно метку искать по коду глазами, и пока ты не найдешь все метки глазами - ты не поймешь что там происодит. А это уже -10 к читабельности кода. Если меток больше 1 и раскиданы по функции это уже -50 к читабельности кода. В итоге функция может быть и простой, но только не удобочитаемой.

Цитата OpenGL @
Капитан, перелогинься :lool: Кто тут с этим спорит вообще? Ну да, может и не найти, и в этом случае лучше написать без goto. Но ведь может и найти - что тогда?

Ну ты же сравнивал предположение с моим утверждением :-? Я не отрицал что может и найти. Я утверждал что goto - зло и Говнокод. Говнокод любой, так же имеет полное право на жизнь. Ты путаешь причину со следствием.

Цитата OpenGL @
Ты сам посчитаешь, сколько раз я говорил, что я не пишу на Си, поэтому самое частое применение goto - прыжок к очистке - мне не нужен, или это сделать мне?

Слушай, мне уже интересно даже стало - на чем же ты пишешь? В С++ что нет goto? Да блин goto наверное разве что в sql каком нибудь и в функциональных языках нет. А в импирических он помоему везде есть. Когда писал на Си, ты же говорил что писал на Си - почему не прыгал из циклов? Не применял goto? Как же так?

Цитата OpenGL @
Внимание, вопрос - кто тут говорит, что надо писать программу, везде пихая goto? :D

Вы говорите. Даже придумали шаблон какой то. В вашем мире почти в каждой программе приходится прыгать из вложенных функций в конец функции для очистки ресурсов и т.п.

Цитата OpenGL @
Вау. А венгерский алгоритм, алгоритм Флойда или вышеописанная мной задача, где я "использовал" goto - перебор всех аргументов в функции f(x, y, z) ты тоже будешь разбивать на функции? :crazy:

Так я же написал - в 95% случаях я не юзаю больше двух вложенных циклов, но есть места - где юзаю, либо от лени, либо от специфики задачи. Что не понятно то?

Цитата OpenGL @
А что такого? Я считаю, что юзать goto там, где он к месту - нормально. Можно даже усилить - юзать %something% там, где оно к месту - нормально. Ну а почему я сам это не делаю - на это может быть тысяча причин. Или ты делаешь всё, что считаешь нормальным? :crazy:

Ага, только вот на практике таких мест нету. И привести такие места вы не в состоянии, ну разве что только велосипедами.

Цитата OpenGL @
Я в курсе, что ты это говорил, но поскольку ты старательно пытаешься доказать, что goto, когда оно в тему, на самом деле всё ухудшает - я просто записал эту твою фразу в обычное балабольство :D

Вся проблема в том, что "тут goto в тему" - это утопия. Это вымышленный рай для наркомана. Понимаешь? В теории может быть и есть такие места, а на практике их нет, есть либо лень, либо безысходность от того, что кто то вот так все криво написал, и времени переписывать у тебя нет. Но это не значит что это хорошее место для использования goto, это значит что это плохое место в принципе, и просто не хватило времени/сил/желания от него избавится и придется потом жить с этим всю оставшуюся жизнь!

Добавлено
Цитата JoeUser @
Но оверхед на проверках явный.

Ага, а то что там Sleep(1) стоит в цикле - тебя значит нисколько не смутило? :D
Цитата KILLER @
Ага, а то что там Sleep(1) стоит в цикле - тебя значит нисколько не смутило?

Мы же говорим о количестве операций, а не о времени. Я не знаю как там реализован слип, но в реализации без goto необоснованно больше тратятся энергоресурсы нашей планеты! 8-)
Мои программные ништякиhttp://majestio.info
Цитата D_KEY @
Но на работе я бы вообще сделал шаг назад и посмотрел на другие варианты решения вцелом.

Ну так одно дело переписывать уже существующий код, и другое дело писать с нуля. Существующий код - всегда сложнее модернизировать(особенно если не ты автор), чем переписать с нуля. У меня была лишь цель избавится от goto любыми способами, более менее приемлемыми. Как только выкинул из цикла сохранение в файл, тут же стал понятен алгоритм работы программы, и в голову начали лезть мысли, как это все можно переписать без goto.
Цитата D_KEY @
Но на работе я бы вообще сделал шаг назад и посмотрел на другие варианты решения вцелом.

"Другие варианты" решения описанной задачи в студию :-?

Цитата D_KEY @
Зато с использованием уже проблем не будет, там будет ясно, что и зачем делается

Ога, вот только выглядеть в целом будет всё как-то так :crazy: Городить некий итератор, нужный только в одном месте и который менее читаемый, чем вариант втупую - глупость уровня Кили.
Подпись была включена в связи с окончанием срока наказания
Цитата OpenGL @
"Другие варианты" решения описанной задачи в студию :-?

Слегка убрал оверхед до одной лишней проверки :)

ExpandedWrap disabled
    #include <iostream>
    #include <fstream>
     
    using namespace std;
     
    bool NeedRestore() {
      ifstream f("saved.txt");
      return f.good();
    }
     
    void FuncSave(const int a, const int b, const int c) {
      ofstream f("saved.txt");
      f << a << "\n" << b << "\n" << c;
    }
     
    void FuncRestore(int& a, int& b, int& c) {
      ifstream f("saved.txt");
      cout << "Восстанавливаемся и продолжаем ..." << endl;
      f >> a >> b >> c;
    }
     
    int main() {
      bool R = NeedRestore();
      for(int i=0; i<5; i++) {
        for(int j=i; j<5; j++) {
          for(int k=j; k<5; k++) {
            if (R) {
              FuncRestore(i,j,k);
              R = false;
              continue;
            }
            // делаем важное дело
            cout << i << ":" << j << ":" << k << endl;
            // эмуляция прерывания
            if (i==2 && j==2 && k==2) {
              cout << "Прервемся на 2:2:2 и сохраняемся" << endl;
              FuncSave(i,j,k);
              return 0;
            }
          }
        }
      }
      return 0;
    }
Мои программные ништякиhttp://majestio.info
О, Киля проснулся. И как обычно - несёт какую-то чушь, на которую уже были даны ответы :lool:

Цитата KILLER @
Слушай, а хорошую ты позицию занял, выдумал какую то хрень, и топишь за нее. cppasm почему то не догадался придраться к тому, к чему придрался ты.

Он придрался ровно к тому же, что и я, просто у кого-то с пониманием контекста проблемы :D

Цитата KILLER @
Хорошо написанный код - я бы понял сразу, просто кинув взгляд(за исключением алгоритмов и разных вычислений). Тут нужно метку искать по коду глазами, и пока ты не найдешь все метки глазами - ты не поймешь что там происодит.

Зачем её искать? Инструкция goto ok - очевидно, означает переход к варианту, когда ок. Тебе не очевидно? Могу только посочувствовать твоей альтернативной понятливости :D

Цитата KILLER @
Я не отрицал что может и найти. Я утверждал что goto - зло и Говнокод. Говнокод любой, так же имеет полное право на жизнь. Ты путаешь причину со следствием.

Имеет, но приводимые тут примеры к говнокоду не относятся - более понятно ты их не напишешь.

Цитата KILLER @
Вы говорите. Даже придумали шаблон какой то. В вашем мире почти в каждой программе приходится прыгать из вложенных функций в конец функции для очистки ресурсов и т.п.

Вообще-то таки есть - почти в каждой. Вот только почти каждая программа пишется на языках, где есть finally, деструкторы или defer-ы, из-за чего ... а впрочем, это уже минимум четвёртый раз в теме говорится, до тебя один фиг не дойдёт это :D

Цитата KILLER @
Слушай, мне уже интересно даже стало - на чем же ты пишешь? В С++ что нет goto? Да блин goto наверное разве что в sql каком нибудь и в функциональных языках нет. А в импирических он помоему везде есть. Когда писал на Си, ты же говорил что писал на Си - почему не прыгал из циклов? Не применял goto? Как же так?

:crazy:
Киля, если ты прочитаешь тот пост, на который ты отвечаешь, то на вопросы - почему я не юзал goto в си и почему не юзаю сейчас - ты увидишь. Ты, конечно, не особо понятливый, но на это уж тебя должно хватить :D

Цитата KILLER @
Ага, только вот на практике таких мест нету. И привести такие места вы не в состоянии, ну разве что только велосипедами.

Ну давай посчитаем, какие примеры тут приводили
1) Выход из множественных циклов. Очевидно, решается без goto не всегда - вынос в отдельную функцию может быть неудобен, если цикл внутри юзает много переменных, локальных для функции, где лежит этот множественный цикл. Ситуация нечастая, но бывает.
2) Переход к очистке ресурсов. Вынос в отдельную функцию неудобен по той же причине, что и предыдущий пункт, а do..while мало того, что вырвиглазный и создаёт дополнительный отступ, так ещё и помешает выходить из циклов. Вывод - в си не решается без attribute cleanup и прочих нестандартных расширений в принципе. По-моему самый частый случай его использования, так что неудивительно, что переход к другому языку, убирая необходимость в этом самом частом частом использовании, практически полностью убирает необходимость в самом goto.
3) Пример Qraizer-а. Никто, включая тебя, более понятный код не написал.
4) Примеры с различных известных сишных проектов и, особенно, "первая функция с goto" из исходников nginx. Может быть переписана без него, но за счёт копипаста с вызовом return other_function(some_parameters), что менее читаемо - понять, в каких случаях функция вернёт ok, будет сложнее, чем в текущем варианте. Но, впрочем, конкретный вариант без goto усложняется не сильно - можно считать его приемлемым, если тебе от этого будет легче.
Подпись была включена в связи с окончанием срока наказания
Цитата OpenGL @
Он придрался ровно к тому же, что и я, просто у кого-то с пониманием контекста проблемы :D

Хорошо, если там будет мега лютая логика - я заведу флаг выхода из цикла и вставлю проверку - если мы не выпрыгнули из вложенного цикла, значит будет выполнятся код за циклом, иначе клинап и выход.
Ты можешь сказать - что там может быть мешанина из кода и будет все запутано. На что я отвечу, если будет такая мешанина, значит я код за циклом и до очистки - вынесу в отдельную функцию, тогда будет все понятно. Так сложно гадать на велосипедах что там будет. Но то, до чего ты прицепился - абсолютно не существенная проблема.

Цитата OpenGL @
Зачем её искать? Инструкция goto ok - очевидно, означает переход к варианту, когда ок. Тебе не очевидно? Могу только посочувствовать твоей альтернативной понятливости :D

В самом переходе - нет ничего плохо, я имею ввиду в конструкции goto label, проблема не в самом переходе, а в месте куда ты переходишь, то есть в самой метке. Вот в ней проблема, именно она и создает неочевидности. Сама же конструкция goto label - ничего криминального в себе не имеет, она подобна break/return/еще чему то подобному.
В случае с циклами - там есть блоки! Сейчас любая среда разработки позволяет без потери контеста прыгать по блокам, нажатием 1-2 кнопок, а с меткой не так. Тебе ее во первых нужно сначало найти глазами, если функция большая и запутанная - ты будешь ее искать поиском, если файл на 5 тысяч строк, и метка одна на функцию, но есть такая же в других функциях - ты по поиск тупо вылетишь за контекст функции.
Если бы IDE позволяли двиг аться по меткам как например по блокам - я думаю его говнокодность тут же бы упала на 50% как минимум. А IDE даже не подсвечивают метку, я уж не говорю о том, чтоб по ним можно было перемещаться. Да ты можешь сказать что в большинстве IDE есть закладки(bookmarks), которые можно поставить на метки. Но ведь - это лишняя работа, которая занимает время и отвлекает.

Цитата OpenGL @
Имеет, но приводимые тут примеры к говнокоду не относятся - более понятно ты их не напишешь.

Потому что это велосипеды.

Цитата OpenGL @
Вообще-то таки есть - почти в каждой. Вот только почти каждая программа пишется на языках, где есть finally, деструкторы или defer-ы, из-за чего ... а впрочем, это уже минимум четвёртый раз в теме говорится, до тебя один фиг не дойдёт это :D

Нет, ты передергиваешь, речь не о return'ах каких нибудь, потому что return'ом ты вылетишь в другую функцию, а с помощью меток ты можешь сделать сложный цикл. И что там намудрил автор юзая метки - еще понять нужно, а полагаться на то, что все будут использовать goto только так чтоб все было понятно - глупо.

Цитата OpenGL @
Киля, если ты прочитаешь тот пост, на который ты отвечаешь, то на вопросы - почему я не юзал goto в си и почему не юзаю сейчас - ты увидишь. Ты, конечно, не особо понятливый, но на это уж тебя должно хватить :D

Ты не переживай. Я читал, и понял. Потому что ты не сталкивался с такими ситуациями. И не столкнешься в 99.9999% случаев в будущем. Именно по этому goto зло. А когда столкнешься - то это будет исключительный случай. У майкрософта же - метки используются везде где нужно или нет. Ты когда будешь писать такой код, который пишут они 100% метки не будешь использовать, ровно как и любой другой вменяемый разработчик.

Цитата OpenGL @
Ну давай посчитаем, какие примеры тут приводили

Это все велосипеды и надуманные примеры. В реальности таких ситуаций ни у меня, ни у тебя не возникало.

Цитата OpenGL @
4) Примеры с различных известных сишных проектов и, особенно, "первая функция с goto" из исходников nginx.

Потому что это они так написали, а не потому что там goto просится. Именно по этому вы и приводите эти примеры.

Добавлено
Цитата JoeUser @
Слегка убрал оверхед до одной лишней проверки :)

У тебя из за continue выходит не хилый оверхед. На сколько я помню - continue - дорогая операция в цикле, и ее нужно избегать.

Добавлено
Ну хотя он там выполняется 1 раз всего. В принципе ниче в нем криминального нет. Я просто не доглядел. Думал он там всегда выполняется.
Сообщение отредактировано: KILLER -
Цитата KILLER @
Хорошо, если там будет мега лютая логика - я заведу флаг выхода из цикла и вставлю проверку - если мы не выпрыгнули из вложенного цикла, значит будет выполнятся код за циклом, иначе клинап и выход.

Это если у тебя один цикл. А если несколько мест, откуда ты выйти можешь? Десяток флагов для каждого из них вводить? :D

Цитата KILLER @
В случае с циклами - там есть блоки! Сейчас любая среда разработки позволяет без потери контеста прыгать по блокам, нажатием 1-2 кнопок, а с меткой не так. Тебе ее во первых нужно сначало найти глазами, если функция большая и запутанная - ты будешь ее искать поиском, если файл на 5 тысяч строк, и метка одна на функцию, но есть такая же в других функциях - ты по поиск тупо вылетишь за контекст функции.

То есть для блоков ты не гнушаешься использовать воможности IDE, а для меток - ни-ни, только примитивный текстовый поиск? :D

Цитата KILLER @
А IDE даже не подсвечивают метку, я уж не говорю о том, чтоб по ним можно было перемещаться.

Как минимум студия умеет и подсвечивать, и переходить к ним. Причём переход ровно такой же, как переход к функции - делается в отдельном окне. Что тебя не устраивает?

Цитата KILLER @
речь не о return'ах каких нибудь, потому что return'ом ты вылетишь в другую функцию, а с помощью меток ты можешь сделать сложный цикл.

А что - сложный цикл на других конструкциях нельзя сделать по-твоему? :crazy: А если можно, то почему тогда плохо именно goto?

Цитата KILLER @
а полагаться на то, что все будут использовать goto только так чтоб все было понятно - глупо.

А кто тут на это полагается? :D
Подпись была включена в связи с окончанием срока наказания
Цитата OpenGL @
Это если у тебя один цикл. А если несколько мест, откуда ты выйти можешь? Десяток флагов для каждого из них вводить? :D

Нетз, значит моя функция примет радикально иной вид, возможно она превратится в десяток других функций, возможно она превратится в класс, возможно что угодно. Я не могу тебе точно сказать что с ней будет, потому что мы сейчас гадаем.

Цитата OpenGL @
То есть для блоков ты не гнушаешься использовать воможности IDE, а для меток - ни-ни, только примитивный текстовый поиск? :D

А что для меток есть? Я их не юзаю, по этому не вкурсе что для них есть в IDE?

Цитата OpenGL @
Как минимум студия умеет и подсвечивать, и переходить к ним. Причём переход ровно такой же, как переход к функции - делается в отдельном окне. Что тебя не устраивает?

У меня студия почему то метки не подсвечивает. Стоят стандартные настройки. И как по ним перемещаться? Плюс ко всему - возьми примитивную IDE, notepad++ или mcedit, far-edit, там вообще нет перемещения даже по блокам. Но тем не менее когда ставишь курсор на открывающийся блок - закрывающийся тут же подсвечивается.

Цитата OpenGL @
А что - сложный цикл на других конструкциях нельзя сделать по-твоему? :crazy: А если можно, то почему тогда плохо именно goto?

Можно. Я же объяснял почему плохо с goto. Потому что куда ты перейдешь - не всегда очевидно в случае с goto. В ряде случаев ты даже под отладчиком можешь запутаться с метками.

Цитата OpenGL @
А кто тут на это полагается? :D

Ну вы ведь. :-?
Цитата KILLER @
В ряде случаев ты даже под отладчиком можешь запутаться с метками.

Ассемблерные демоны уже взяли тебя на карандаш, готовься к пожизненной скороварке! :blink:
Мои программные ништякиhttp://majestio.info
Цитата OpenGL @
Городить некий итератор, нужный только в одном месте и который менее читаемый, чем вариант втупую - глупость уровня Кили.

Ну если так, то согласен.
Но я бы не хотел видеть тот говнокод с goto в проде. В крайнем случае вариант Кили.
А если это не "одноразовый" код, то я бы таки подумал :)
"If someone claims to have the perfect programming language, he is either a fool or a salesman or both"(c) Bjarne Stroustrup
Цитата JoeUser @
Ассемблерные демоны уже взяли тебя на карандаш, готовься к пожизненной скороварке! :blink:

мы сейчас говорим не об ассемблере. Там очень ограниченные средства разработки, нежели в ЯВУ, и там goto скорее правило, чем исключение из правил.
Цитата KILLER @
етз, значит моя функция примет радикально иной вид, возможно она превратится в десяток других функций, возможно она превратится в класс, возможно что угодно. Я не могу тебе точно сказать что с ней будет, потому что мы сейчас гадаем.

Не всегда возможно. Вот прямо сейчас у меня есть такая функция - три больших отдельных цикла, в них идёт построение сложных структур данных (используется несколько локальных переменных), везде нужны проверки, что всё хорошо, и если не всё - все построенные структуры надо удалить. В си в этой функции у меня бы было goto, выполняющее освобождение всех временных ресурсов - без него написать бы удобно всё это дело тупо не получилось.

Цитата KILLER @
А что для меток есть? Я их не юзаю, по этому не вкурсе что для них есть в IDE?

Как минимум - настройки цвета и переход к метке по аналогии с go to definition для методов.

Цитата KILLER @
Плюс ко всему - возьми примитивную IDE, notepad++ или mcedit, far-edit, там вообще нет перемещения даже по блокам. Но тем не менее когда ставишь курсор на открывающийся блок - закрывающийся тут же подсвечивается.

Ага - блок у тебя обязательно помещается в экран, а вот метка по-любому находится так далеко, что ты её не найдёшь :lool: Двойные стандарты такие двойные.

Цитата KILLER @
Можно. Я же объяснял почему плохо с goto. Потому что куда ты перейдешь - не всегда очевидно в случае с goto. В ряде случаев ты даже под отладчиком можешь запутаться с метками.

И? :rolleyes: Я могу if-ами добиться того же - теперь if-ы зло, или всё-таки это я такой негодяй, написавший такую неудобную программу? :D

Цитата KILLER @
Ну вы ведь.

То есть по-твоему "goto иногда может быть к месту" означает "все должны использовать goto правильно"? :crazy:
Подпись была включена в связи с окончанием срока наказания
Цитата OpenGL @
Не всегда возможно. Вот прямо сейчас у меня есть такая функция - три больших отдельных цикла, в них идёт построение сложных структур данных (используется несколько локальных переменных), везде нужны проверки, что всё хорошо, и если не всё - все построенные структуры надо удалить. В си в этой функции у меня бы было goto, выполняющее освобождение всех временных ресурсов - без него написать бы удобно всё это дело тупо не получилось.

Ну приведи хоть псевдокодом. Чтоб понимать на примере. Иногда используют goto от того, что мало знают инструмент. Т.е. допустим ты бы юзнул goto, а ктото другой возможно другой механизм бы.

Цитата OpenGL @
Как минимум - настройки цвета и переход к метке по аналогии с go to definition для методов.

В настройках лазить? А если у меня две метки? Куда меня go to definition отправит? И как вызвать этот go to definition, например в MSVS?

Цитата OpenGL @
Ага - блок у тебя обязательно помещается в экран, а вот метка по-любому находится так далеко, что ты её не найдёшь :lool: Двойные стандарты такие двойные.

Если у меня блок помещается в экран - то там темболее не нужны goto, их обычно и юзают там, где не помещается в экран, чтоб еще подлить говнеца в итак портянку кода. :D

Цитата OpenGL @
И? :rolleyes: Я могу if-ами добиться того же - теперь if-ы зло, или всё-таки это я такой негодяй, написавший такую неудобную программу? :D

Дело в том, что с if'ами ты можешь такое сделать или специально или если зеленый. А с goto практически всегда выходит непонятно.

Цитата OpenGL @
То есть по-твоему "goto иногда может быть к месту" означает "все должны использовать goto правильно"? :crazy:

Я приводил исходники от MS, где goto абсолютно не к месту, более того там для отчистки ресурсов в языке есть встроенные средства - аля те же деструкторы, а вы мне говорили что это какой то мега шаблон и супер пупер клевый код, но никак не говно. Именно по этому мы и спорим 8-ую страницу.
KILLER, ну не ври, что читаешь, а.
Одни с годами умнеют, другие становятся старше.
Цитата Qraizer @
KILLER, ну не ври, что читаешь, а.

Читаю. :-? Вас же из стороны в сторону носит. Приводишь микрософтовский код на плюсах с goto - нормально. Потом пишите что в С++ есть деструкторы. Потом опять что нормально. Я в этом не виноват. Я там раньше про RAII писал зачем? Не затем ли, что вы мне говорили что для очистки ресурсов сойдет и goto?
Сообщение отредактировано: KILLER -
Цитата KILLER @
Ну приведи хоть псевдокодом.

На си это примерно так бы выглядело:
ExpandedWrap disabled
    void rebuild()
    {
        // Инициализация новых структур данных в локальных переменных
        ...
     
     
        // Построение первых структур данных
        for(...)
        {
            ...
            if(...) goto cleanup;
        }
     
        // Построение вторых структур данных
        for(...)
        {
            ...
            if(...) goto cleanup;
        }
     
        // Окончательное построение и проверка
        for(...)
        {
            ...
            if(...) goto cleanup;
        }
     
        // Если мы здесь, то уже всё хорошо - просто обмениваем указатели на текущие структуры и построенные.
        ...
    cleanup:
        // Удаление всех локальных структур
    }

Даже если ты заморочишься и вынесешь каждый этап построения в отдельную функцию, у тебя получится говно вроде такого:
ExpandedWrap disabled
    if(build1(100500_local_variables_passed_by_pointers) &&
       build2(100500_local_variables_passed_by_pointers) &&
       build3(100500_local_variables_passed_by_pointers))
    {
       swap_pointers;
    }
    cleanup

либо, как вариант - делать кучу вложенных if-ов. Оба эти решения проиграют по всем параметрам решению в лоб с goto.


Цитата KILLER @
В настройках лазить? А если у меня две метки? Куда меня go to definition отправит? И как вызвать этот go to definition, например в MSVS?

Если у тебя две метки в пределах одной функции, то у них разные имена, иначе программа просто не скомпилится :D Какая клавиша у тебя - понятия не имею, смотри там же в настройках. Что за вопросы-то тупые? :D

Цитата KILLER @
Если у меня блок помещается в экран - то там темболее не нужны goto, их обычно и юзают там, где не помещается в экран, чтоб еще подлить говнеца в итак портянку кода.

Ога, а то, что тут был не один такой пример - ты, как обычно, не заметил :D

Цитата KILLER @
Дело в том, что с if'ами ты можешь такое сделать или специально или если зеленый. А с goto практически всегда выходит непонятно.

А что - для непонимания описанных тут примеров зелёным быть не надо что ли? :crazy:

Цитата KILLER @
Я приводил исходники от MS, где goto абсолютно не к месту, более того там для отчистки ресурсов в языке есть встроенные средства - аля те же деструкторы, а вы мне говорили что это какой то мега шаблон и супер пупер клевый код, но никак не говно. Именно по этому мы и спорим 8-ую страницу.

Видимо, недостаточно ясно :lool:
Цитата OpenGL @
Да, я от тебя на данный конкретный вопрос ответ получил, он меня впоне устроил и новых вопросов по этому поводу у меня нет. Можно считать вопрос о говнокоде в MS SDK закрытым, или я всё ещё недостаточно ясно выразился, что я с этим не спорю от слова совсем?
Подпись была включена в связи с окончанием срока наказания
Цитата KILLER @
На сколько я помню - continue - дорогая операция в цикле, и ее нужно избегать.

Киля, извини, чисто ради интереса - приведи пруф на счет "дороговизны" оператора "continue".
Чуйка подсказывает подлог, обман и мошенничество :lol:
Мои программные ништякиhttp://majestio.info
Цитата KILLER @
Вас же из стороны в сторону носит. Приводишь микрософтовский код на плюсах с goto - нормально. Потом пишите что в С++ есть деструкторы. Потом опять что нормально. Я в этом не виноват. Я там раньше про RAII писал зачем? Не затем ли, что вы мне говорили что для очистки ресурсов сойдет и goto?

Цитата OpenGL @
Видимо, недостаточно ясно
:yes:
Цитата Qraizer @
На предмет goto в библиотеках MS.
Исключения полноценно стали поддерживаться только в VC4.2, который увидел свет в 1998-ом, незадолго до VC6. До этого компилятор их понимал очень ограничено, а до версии 4.0 (вроде бы) не понимал вообще. Библиотека MFC увидела свет в ...1992-ом, ещё на 16-битном Microsoft Quick C for Windows. Соответственно потому в MFC есть собственные exception-макросы. ATL разрабатывалась попозже, но не сильно. Первые версии вошли в, если не ошибаюсь, тот же VC4.2. Соответственно использование там C++EH было, наверное возможным, но были, видать, причины не раскачивать лодку. Тем более, что совмещение SEH с C++EH в пределах одной программы всё-таки и сегодня иногда вызывает определённые сложности.
:wall:
Одни с годами умнеют, другие становятся старше.
Цитата OpenGL @
На си это примерно так бы выглядело:

Почему нельзя написать например как то так:
ExpandedWrap disabled
    pointer1* Build1()
    {
        // Построение первых структур данных
        for(...)
        {
            ...
            if(...) break
        }
        cleanup
    }
     
    pointer2* Build2()
    {
        // Построение вторых структур данных
        for(...)
        {
            ...
            if(...) break
        }
        cleanup
    }
     
    pointer3* Build3()
    {
        // Окончательное построение и проверка
        for(...)
        {
            ...
            if(...) break
        }
        cleanup
    }
     
    void rebuild()
    {
        // Инициализация новых структур данных в локальных переменных
        ...
     
        pointer1 =  Build1();
        pointer2 =  Build1();
        pointer3 =  Build1();
     
        // Если мы здесь, то уже всё хорошо - просто обмениваем указатели на текущие структуры и построенные.
        ...
    cleanup:
        // Удаление всех локальных структур
    }


Цитата OpenGL @
Если у тебя две метки в пределах одной функции, то у них разные имена, иначе программа просто не скомпилится :D Какая клавиша у тебя - понятия не имею, смотри там же в настройках. Что за вопросы-то тупые? :D

Вопросы тупые от того, что при написании метки - мне Intellisense не показывает даже ее имя. Если ты с goto не работаешь, интересно с чего ты взял что это есть в студии? Максимум что я вижу, это подсветка метки, когда ставишь курсор на goto. Ну и goto definition работает в одну сторону.

Цитата OpenGL @
Ога, а то, что тут был не один такой пример - ты, как обычно, не заметил :D

Дело в том, что с другими конструкциями языка либо не нужно куда то прыгать и смотреть, либо делать это не так сложно.

Цитата OpenGL @
А что - для непонимания описанных тут примеров зелёным быть не надо что ли? :crazy:

С goto можно быть хоть зеленым, хоть фиолетовым и всеравно выдать говнокод. С другими операторами языка это не так.

Цитата OpenGL @
Видимо, недостаточно ясно :lool:

Так вас же много, а я один. Я вас всех рассматриваю как одного собеседника. Поэтому пока все не признают что С++ код у МС с метками - говнокод, буду считать что вы все мне втираете одно и то же.
Скрытый текст
Цитата Qraizer @
Оператор "следования" - божественнен :lool:
Мои программные ништякиhttp://majestio.info
Цитата KILLER @
Почему нельзя написать например как то так:

:lool:
Я ровно такой вариант написал чуть ниже, добавив необходимые проверки.


Цитата KILLER @
Если ты с goto не работаешь, интересно с чего ты взял что это есть в студии?

А проверить это же так тяжелоооо, просто ужас :D

Цитата KILLER @
Дело в том, что с другими конструкциями языка либо не нужно куда то прыгать и смотреть, либо делать это не так сложно.

Прыгать? :lool: Киля, в этой ветке дискуссии речь ведётся о функциях, влезающих в один экран, в которых прыгать никуда не надо априори, и которые с goto тоже бывают более читабельные. Ты специально только делаешь вид, что ведёшь себя глупо, или это результат настоящего и всамделишного полёта мысли? :crazy:

Цитата KILLER @
Так вас же много, а я один. Я вас всех рассматриваю как одного собеседника. Поэтому пока все не признают что С++ код у МС с метками - говнокод, буду считать что вы все мне втираете одно и то же.

О, надо же. Ты прямым текстом признался, что не читатель. Уважуха! 8-) Не каждый может признать за собой недостатки :yes:
Сообщение отредактировано: OpenGL -
Подпись была включена в связи с окончанием срока наказания
Qraizer, то что ты описываешь никак не может объяснять нафига юзать goto в коде. По вашим словам получается что в последний раз они код писали в в 98 году что ли? Свежий код, старый, любой код майкрософта пестрит goto.

Добавлено
Цитата OpenGL @
Я ровно такой вариант написал чуть ниже, добавив необходимые проверки.

Ну у тебя там вызов трех функций в if выражении получился, что действительно в твоем примере смахивает на говно. А у меня сначало все это присваивается указателем. По твоему ты не будешь if пихать на проверку не нулевого указателя или что? Так что либо получается необоснованное с твоей стороны "говно", либо ты что то не договариваешь.

Цитата OpenGL @
А проверить это же так тяжелоооо, просто ужас :D

Ну так я проверил. Метка не подсвечивается в синтаксисе языка. Переход - разве что по F12, но он работает вообще практически на любой конструкции языка, это не для меток сделано. Больше я ничего не нашел :-?

Цитата OpenGL @
Прыгать? :lool: Киля, в этой ветке дискуссии речь ведётся о функциях, влезающих в один экран, в которых прыгать никуда не надо априори, и которые с goto тоже бывают более читабельные. Ты специально только делаешь вид, что ведёшь себя глупо, или это результат настоящего и всамделишного полёта мысли? :crazy:

В этой ветке дискуссии вы приводите либо выдуманные функции, которые занимают 5 строчек кода, и где можно легко обойтись и без goto, либо ссылки на код функций по 150 строчек кода.

Цитата OpenGL @
О, надо же. Ты прямым текстом признался, что не читатель. Уважуха! 8-) Не каждый может признать за собой недостатки :yes:

Где? Ну вот где я признался что я не читатель? Хорошо, если ты согласен что писать goto в С++ оцтой, почему ты тогда пытаешься оправдать код на С++ с использованием goto ? напиши тогда - Да, в С++ вот тут говнецо. А если бы код был бы Сишный, тогда возможно и норм. Тогда к тебе лично вопросы отпадут. Но вы сначало пишите что в С++ никто никогда в проде goto не использовал, мол де есть же RAII, а потом пишите - ну и что тут такого, обычная практика. Да где же это обычная практика, если даже K&R в бородатых 80-х писали что нифига это не нормально даже для Си, ну кроме некоторых случаях. Не для С++, а для Си!!!

А вы мне втираете - что это чуть ли не единственный способ решить задачу очистки ресурсов.

Добавлено
Короче ладно. Хватит переливать из пустого в порожнее. Я по прежнему остался при своем. goto используют люди из за ограниченности мышления, либо из за лени ну и в качестве костылей. Больше ему нет нигде нормального применения.
Если будете возражать, попробуйте придумать задачу, нормальную, не костыль вставить, а обычную такую задачу, где без него не обойтись. Тогда будем говорить. а так реально уже задолбало. выходит разговор глухого со слепым.
Сообщение отредактировано: KILLER -
Цитата KILLER @
Больше ему нет нигде нормального применения.

А как же явный оверхед при замене функционала?
Или ты что, реально решил померятmся таймерами штоле?
Мои программные ништякиhttp://majestio.info
Цитата KILLER @
Ну у тебя там вызов трех функций в if выражении получился, что действительно в твоем примере смахивает на говно. А у меня сначало все это присваивается указателем. По твоему ты не будешь if пихать на проверку не нулевого указателя или что? Так что либо получается необоснованное с твоей стороны "говно", либо ты что то не договариваешь.

А, то есть ты даже не видишь, что, вставив проверки в твой код, ты получишь ровно то, что написано у меня? :lool:

Цитата KILLER @
Метка не подсвечивается в синтаксисе языка.

Логично - по дефолту она того же цвета, что и остальной текст. Но ты в настройках волен поменять цвет хоть на серобуромалиновый :D

Цитата KILLER @
Переход - разве что по F12, но он работает вообще практически на любой конструкции языка, это не для меток сделано

И что? :crazy:

Цитата KILLER @
В этой ветке дискуссии вы приводите либо выдуманные функции, которые занимают 5 строчек кода, и где можно легко обойтись и без goto, либо ссылки на код функций по 150 строчек кода.

Невнушабельно. Давай для пущей убедительности функции в 1 строку с одной стороны, и 424242 строки - с другой :crazy:

Цитата KILLER @
Да где же это обычная практика, если даже K&R в бородатых 80-х писали что нифига это не нормально даже для Си, ну кроме некоторых случаях.

И это притом, что в книге есть цитата наподобие "впрочем, покажем примеры, где goto может быть в тему"? :crazy:

Цитата KILLER @
Я по прежнему остался при своем. goto используют люди из за ограниченности мышления, либо из за лени ну и в качестве костылей.

Ну в этом, полагаю, никто тут не сомневается - что факты не способы поколебать твою упёртость истина достаточно очевидная :D
Сообщение отредактировано: OpenGL -
Подпись была включена в связи с окончанием срока наказания
Цитата KILLER @
Qraizer, то что ты описываешь никак не может объяснять нафига юзать goto в коде. По вашим словам получается что в последний раз они код писали в в 98 году что ли? Свежий код, старый, любой код майкрософта пестрит goto.

Нет. Просто не меняют однажды вымученное из-за ограничений, но работающее. А что, надо сразу же броситься тут же отперерефактнить всё нахрен? Платишь?
Знаешь ли, когда половина проекта в одной парадигме, другая в другой – это тоже говнокод. Так что ежели чё там новое добавляется, хотя, насколько мне известно, MS давно положила болт на развитие MFCей с ATLями, так уж пусть будет лучше в едином стиле.

Добавлено
Цитата KILLER @
напиши тогда - Да, в С++ вот тут говнецо. А если бы код был бы Сишный, тогда возможно и норм.
Ну я фактически именно это и сделал. Запостил код на C, и попозже два его аналога на C++.

Добавлено
Цитата KILLER @
А вы мне втираете - что это чуть ли не единственный способ решить задачу очистки ресурсов.
Почему единственный-то? Наглядный, простой и быстрый. Другие "вычеркните что-нибудь одно и приходите к нам" ©.

Добавлено
Цитата KILLER @
Больше ему нет нигде нормального применения.
Он находит применение в неструктурных алгоритмах. Представь себе блоксхему с входом/выходом в/из середины. Не встречал? Ну что сказать, бывает...
Одни с годами умнеют, другие становятся старше.
Цитата OpenGL @
А, то есть ты даже не видишь, что, вставив проверки в твой код, ты получишь ровно то, что написано у меня? :lool:

У тебя проверяется результат функции, а в моем случае будет проверка указателей. Ну конечно, одно и то же. ты небось еще и в циклах пишешь нечто подобное?
ExpandedWrap disabled
    for(SomeIteratorObject ItObj = GetBegin(); ItObj != GetHeavyEnd(); ++ItObj)

?
Если ты подразумевал конкретно указатели - обоснуй в чем заключается говно при таком подходе, который предложил ты и продублировал по твоему я? нонче не модно указатели проверять ноль? Или может быть модно пихать везде и всюду goto?
Вот я не понимаю реально - ты кричишь, я не предлагаю использовать goto везде, но иногда его можно применить. При этом ты приводишь код, который может легко обойтись без всяких goto, и будет восприниматься легче, чем аналог с goto. Может для тебя на данном этапе спора goto читабельнее остальных конструкций?

Добавлено
Цитата OpenGL @
Логично - по дефолту она того же цвета, что и остальной текст. Но ты в настройках волен поменять цвет хоть на серобуромалиновый :D

Цвет чего? У меня цвет поменяет только метка? Или остальные идентификаторы тоже?

Добавлено
Цитата Qraizer @
Знаешь ли, когда половина проекта в одной парадигме, другая в другой – это тоже говнокод.

Ну как не крути у них и так говнокод и так говнокод, потому что у них есть примеры без goto. Значит они нарушают свою парадигму с goto. Выходит ведь так?

Добавлено
Цитата Qraizer @
Он находит применение в неструктурных алгоритмах. Представь себе блоксхему с входом/выходом в/из середины. Не встречал? Ну что сказать, бывает...

Вообще то я речь завел не о блоксхемах и не о микроконтроллерах каких нибудь. Речь шла про код майкрософта. goto говнокодом был что в 80-х, что сегодня.

Но ваше право отмазывать майкрософт за их говнокод.
KILLER, ты или бесконечно наивен, или так же бесконечно идеалист :) Ну не бывает так, что б в коммерческой компании, не страдающей долей альтруизма, взяли и начали переписывать то, что работает и проверено временем, просто потому, что стандарт поменялся, парадигмы появились и так далее по списку. С формальной точки зрения ты, конечно, прав. Ковырял как-то утёкший код Win2k, местами я ещё в свои первые годы писал лучше, чем то, что было там. Но то, что было там, оно работало. И, скорее всего, работает до сих пор где-то в оставшихся системных утилитах, вроде той же очистки диска. Так зачем это трогать? Что в итоге выиграет корпорация?
char *out = "|*0>78-,+<|"; size_t cc = char_traits<char>::length(out);
for (size_t i=0;i<cc;i++)??<cout<<static_cast<char>((out??(i??)??'89));??>cout<<endl;


user posted image Чат Исходников в СкайпеЧат Исходников в Дискорде — Не проходим, а заходим!

user posted image
Цитата B.V. @
Ну не бывает так, что б в коммерческой компании, не страдающей долей альтруизма, взяли и начали переписывать то, что работает и проверено временем, просто потому, что стандарт поменялся, парадигмы появились и так далее по списку.

Я это очень прекрасно понимаю. И так уж и быть не буду с этим спорить. Пусть будет так. На рефакторинг нужны человекочасы, это определенные трудозатраты и так далее. Но! Но ведь от этого код то лучше не станет? Ведь верно? Если что это риторический вопрос касательно тебя, потому как в следующем предложении ты на него ответил, и я с тобой соглашусь:
Цитата B.V. @
С формальной точки зрения ты, конечно, прав.


Добавлено
Цитата B.V. @
Так зачем это трогать? Что в итоге выиграет корпорация?

Да мне то, по большому счету вообще пофигу какой у них там код, пусть хоть все на goto перепишут. Я не работаю в майкрософт, и не занимаюсь рефакторингом или поддержкой их кода. Я юзаю их функции/классы/библиотеки, работает, да и ладно. Просто спор был конкретно об неком коне в вакууме. Лично я считаю что их код местами лютый говнокод. Это лично мое мнение. Есть у них и очень навороченный код, до которого я даже не дорос еще. Вот по сути и все.
Просто меня начали убеждать, на сколько я понял - поменять свое мнение о их коде, который я считаю говнокодом.

Добавлено
Цитата OpenGL @
И это притом, что в книге есть цитата наподобие "впрочем, покажем примеры, где goto может быть в тему"? :crazy:

Во многих книгах, очень известных авторов так же можно найти описание применения какого нибудь говнокода, с оговоркой "впрочем кое где этим можно кое что заткнуть".
Например у того же Рихтера есть такие примеры.

Добавлено
Цитата Qraizer @
Почему единственный-то? Наглядный, простой и быстрый. Другие "вычеркните что-нибудь одно и приходите к нам" ©.

Ну извиняй, не так сформулировал, я имел ввиду "А вы мне втираете - что это чуть ли не единственный рассово верный способ решить задачу очистки ресурсов."
Посмотри код что привел OpenGL, я не знаю задачу целиком, но его псевдокод - можно легко переписать без goto. И тем не менее, в начале дискуссии он в принципе соглашался с моей позицией. А сейчас кричит, что любой другой вариант - говно нечитабельное, а с goto - ну просто супер пупер код. Я сейчас конкретно не тебя обвиняю Qraizer. Я сейчас просто показываю уровень аргументации.
И ты писал, что в проде не припомнишь чтоб goto юзал. Думаю на Си ты писал побольше чем мы с OpenGL вместе взятые умножить на 10. И тем не менее - я не совсем пониманию твою позицию. То ли ты goto пытаешься отмазать, то ли код майкрософта. При этом из всех споров про goto, я так понял что ты бы его юзнул, в исключительной ситуации. А не как правило. Так я думаю это абсолюнто всех касается, и меня в том числе.
Но приведенные примеры - не являются исключительными ситуациями имхо. Вот взять хотя бы твой код, который вчера я переписывал без goto. Сколько у автора улетело времени на его написание? И почему он сделал именно вот так, а не по другому? Ведь там функция довольно сложная вышла, даже без goto, ее по хорошему нужно было смело бить на три. RestoreStateFromFile, SaveStateFromFile, ну и собственно алгоритм счетчиками. Почему он так не сделал? Мне лично не понятно. Более того, там не goto ломает читабельность, а вырвиглазные reinterpret_cast<char*>(trololo)

Добавлено
Цитата JoeUser @
А как же явный оверхед при замене функционала?
Или ты что, реально решил померятmся таймерами штоле?

Какой оверхед еще? 3 процессорные инструкции оверхед или что?
Сообщение отредактировано: KILLER -
Цитата KILLER @
У тебя проверяется результат функции, а в моем случае будет проверка указателей.

Киля, ты не разглагольствуй, а покажи кодом эти все проверки. Вот вернула build1 ошибку (да пусть даже упростим и предположим, что она только один указатель возвращает, хотя это не так), а значит требуемые для последующих этапов данные не готовы. Надо освободить то, что уже насоздавалось. Твои действия? :rolleyes:

Цитата KILLER @
Если ты подразумевал конкретно указатели - обоснуй в чем заключается говно при таком подходе, который предложил ты и продублировал по твоему я?

Потому что все эти построения делаются в рамках одного единого и неделимого алгоритма, смысл каждой части которого существует только в контексте остальных частей. К тому же алгоритма не особо-то и большого (данная функция занимает всего-то чуть больше 100 строк) и не особо сложного, учитывая, что коллега вот буквально сегодня без моей подсказки быстро внёс в него необходимые изменения, и, я уверен, внёс бы, если бы писалось всё на си с goto. И смысл тогда разбивать алгоритм на функции с кучей параметров, если это только затруднит последующий анализ и займёт больше места, не дав взамен ничего, кроме отсутствия предмета твоей религиозной ненависти? :D

Цитата KILLER @
Цвет чего? У меня цвет поменяет только метка? Или остальные идентификаторы тоже?

Зайди уже в настройки студии, а <_< Как минимум 2015 и выше - настройка цвета меток есть.
Подпись была включена в связи с окончанием срока наказания
Цитата OpenGL @
Вот вернула build1 ошибку (да пусть даже упростим и предположим, что она только один указатель возвращает, хотя это не так), а значит требуемые для последующих этапов данные не готовы.

То ты меня высмеиваешь за то, что я написал то же самое. То задаешь какие то глупые вопросы относительно моего кода. Я ж тебе по функциям расписал. внутри каждой функции есть свой клинап(под ним можешь подразумевать как раз обработку ошибки, произошедшую внутри конкретного конструктора структуры). Если что то не получилось - тебе функция вернет нулевой указатель. Ну а дальше я просто не стал писать if, который ты за меня написал в своем дополнении к своему коду. :-?

Цитата OpenGL @
Потому что все эти построения делаются в рамках одного единого и неделимого алгоритма, смысл каждой части которого существует только в контексте остальных частей.

А что значит неделимый алгоритм? Псевдокод ты написал как раз таки делимый. :-?

Цитата OpenGL @
И смысл тогда разбивать алгоритм на функции с кучей параметров, если это только затруднит последующий анализ и займёт больше места, не дав взамен ничего, кроме отсутствия предмета твоей религиозной ненависти? :D

Ну то что ты привел псевдокодом - бьеться легко на функции. Я же не виноват, что ты не можешь выразить суть задачи псевдокодом. :-?
Более того, то что ты привел - я не вижу там смысла писать goto даже на Си. Ну вот не вижу в упор.

Понимаешь, goto можно влепить куда угодно. И обосновать это твоими словами. Так спорить сложно. Я ожидал, что ты приведешь нечто, что поставит меня в тупик, и вынудит с тобой согласится. А на деле выходит так, что ты приводишь то, что легко переписывается и без goto, но делаешь упор на то, что если бы ты писал на Си, то написал бы обязательно goto(как будто без него пиндец как больно было бы), и твой код все бы поняли. :-?

Я уверен что можно что угодно переписать на goto - и это даже будет понятно. Но зачем писать с goto, если можно написать и без goto? Вот в чем вопрос.

Цитата OpenGL @
Зайди уже в настройки студии, а <_< Как минимум 2015 и выше - настройка цвета меток есть.

Хз, я не нашел :-? Да и раньше я писал, что все не ограничивается одной только MSVS.

Добавлено
По поводу настроек студии, ты можешь не заморачиваться. Я особо и не искал. Ну если есть такая возможность, покрасить отдельно метку в студии - ну есть так есть. Мне в принципе хватает того, что по умолчанию она не покрашена. Дело в том, что в настройки студии я не особо лазаю, так как не ограничен одной только студией.
А вот переход по меткам - было бы интересно услышать как настроить. Может когда пригодится. Я нашел только go to definition, но оно работает в одну сторону, и предназначено не для скакания по меткам.
Цитата KILLER @
Я ж тебе по функциям расписал. внутри каждой функции есть свой клинап(под ним можешь подразумевать как раз обработку ошибки, произошедшую внутри конкретного конструктора структуры)

Нет у функций никакого cleanup - всё, что было создано на предыдущих этапах (включая часть вспомогательных данных, нужных только для построения, т.е. результат работы первого цикла - не один, грубо говоря, массив, а несколько) нужно и на последующих, поэтому единственное место, где всё удаляется - главный cleanup.
Или всё гораздо (нет, ГОРАЗДО) хуже, и ты предлагаешь удалять, например, результаты успешного build1 при неуспехе build2 - в cleanup секции в build2, а также в build3 в случае его неуспеха, куда мы придём в случае успеха build2, и ещё дополнительно - в главной секции cleanup, куда мы придём в случае успеха вообще всего? :crazy:

Цитата KILLER @
Ну то что ты привел псевдокодом - бьеться легко на функции.

Разумеется, бъётся. Только толку-то? :D
Сообщение отредактировано: OpenGL -
Подпись была включена в связи с окончанием срока наказания
Цитата KILLER @
А вот переход по меткам - было бы интересно услышать как настроить. Может когда пригодится.
Можно на метках закладки сразу ставить (Ctrl+K/K), дабы опосля по ним F2 шлёпать.
Цитата Славян @
Можно на метках закладки сразу ставить (Ctrl+K/K), дабы опосля по ним F2 шлёпать.

Славян, про закладки я знаю, иногда даже активно использую, если код запутанный. И раньше писал, что мне видится разве что только закладками метки помечать, чтоб по ним прыгать. Но - это ведь их нужно для начала расставить. А это уже потеря времени, ради понимания происходящего.

Добавлено
Цитата OpenGL @
Нет у функций никакого cleanup - всё, что было создано на предыдущих этапах (включая часть вспомогательных данных, нужных только для построения, т.е. результат работы первого цикла - не один, грубо говоря, массив, а несколько) нужно и на последующих, поэтому единственное место, где всё удаляется - главный cleanup.
Или всё гораздо (нет, ГОРАЗДО) хуже, и ты предлагаешь удалять, например, результаты успешного build1 при неуспехе build2 - в cleanup секции в build2, а также в build3 в случае его неуспеха, куда мы придём в случае успеха build2, и ещё дополнительно - в главной секции cleanup, куда мы придём в случае успеха вообще всего? :crazy:

Мне сложно парировать не зная сути задачи. Извини, но все тузы в данном случае у тебя на руках, а я играю в слепую. Я так не могу спорить.
Цитата KILLER @
Ну извиняй, не так сформулировал, я имел ввиду "А вы мне втираете - что это чуть ли не единственный рассово верный способ решить задачу очистки ресурсов."
И ничего не поменялось. Простой, быстрый, понятный, но уж точно не единственный. KILLER, просто присмотрись: это ровно тот же самый __finally с __leave, только сделан руками, потому что язык встроенных средств не имеет, а компилятор подходящих расширений языка.
Цитата KILLER @
И ты писал, что в проде не припомнишь чтоб goto юзал. ... То ли ты goto пытаешься отмазать, то ли код майкрософта. При этом из всех споров про goto, я так понял что ты бы его юзнул, в исключительной ситуации. А не как правило.
Ну да. Я знаю средства, предоставляемые мне языком, понимаю их достоинства и недостатки, знаю "правила хорошего тона", и не имею предрассудков в аккумуляции всего при принятии решений. Если я увижу, что goto конкретно вот тут не проявляет своих отрицательных сторон, но в сравнении с другими средствами проявляет положительные, заюзаю и не поморщусь. И это справедливо для любых других средств, той же рекурсии, например. Или не дай бог switch(). Ну и если некий код вызывает вопросы типа "нахрена так", то это не означает автоматически, что он плохой. Возможно, были причины написать именно так, которых мы не знаем. Другое дело, чтобы из-за этого "нахрена" коду плохо не стало. Вот на это надо смотреть. Ну так и не стало же. Сколько ссылок ты не давал, столько раз я и приходил к выводу, что мол, да, странно, но вот так тоже нормально, плохих последствий не имеет.
Кстати вот, а почему у тебя switch() не вызывает отторжения? Это же самая что ни на есть неструктурная конструкция, похлеще goto, я бы сказал: у того хоть метка одна, а тут куча, ветвление динамическое по результату выражения, а не статически в конкретную метку, да ещё и без контроля границ вариантов, как было бы при вложенных if()/else. И ещё кстати, на предмет вложенных if(): приемлемая глубина вложения как-то коррелирует с таковой для циклов?
Вишь, сколько вопросов, на которые однозначных ответов нет и быть не может.
Цитата KILLER @
Сколько у автора улетело времени на его написание? И почему он сделал именно вот так, а не по другому? Ведь там функция довольно сложная вышла, даже без goto, ее по хорошему нужно было смело бить на три. RestoreStateFromFile, SaveStateFromFile, ну и собственно алгоритм счетчиками. Почему он так не сделал?
Ну, автором был я. Восстанавливал код по памяти, изначально это был такой же полусинтетический пример для другого ресурса, давно почившего лет за 10 до этого. А тот в свою очередь являлся выжимкой некой вполне практической задачи, писавшейся для однозадачной DOS. Код сохранения/восстановления внедрялся в уже готовую программу, когда выяснилось, что программа будет работать слишком долго, и не факт, что всё это время комп не понадобится для более срочных задач. Почитай, более 20-и лет назад, откуда я помню-то истоки.
Цитата KILLER @
Более того, там не goto ломает читабельность, а вырвиглазные reinterpret_cast<char*>(trololo)
Ну, это не ко мне. Бинарный ввод/вывод у потоков диктует char*, что тут сделаешь.
Сообщение отредактировано: Qraizer -
Одни с годами умнеют, другие становятся старше.
Цитата Qraizer @
это ровно тот же самый __finally с __leave, только сделан руками, потому что язык встроенных средств не имеет, а компилятор подходящих расширений языка.

__finally говно еще то, по крайней мере в С++. Я так понимаю - это уже из области SEH исключений? Я сталкивался с этим, и очень плотно сталкивался, и матюкался и плевался. Потому что когда ты попадаешь в этот блок - фрейм стека теряется напрочь, и ты ничего не можешь сделать, вернее можешь - но это все нужно делать вручную, чтоб сохранить фрейм стека. В Си - возможно это благо и чудо, я не буду спорить, потому как в Си я с этим не работал, но там нет и классов. А я с этой херней работал именно в С++ и с классами. Правда было это довольно давненько, лет 5 назад, а то и 8. Деталей я не помню сейчас. Но! вся эта шняга типа __finally нужна для конкретных вещей. А goto - не нужен для конкретных вещей. И если вылетит Access Violation - __finally в принципе может как то помочь, а вот goto - нет. Потому что это два разных уровня взаимодействия с программой.
Я могу ошибаться конечно, может я что подзабыл или ты что то другое имел ввиду. Я не знаю.

Цитата Qraizer @
Ну да. Я знаю средства, предоставляемые мне языком, понимаю их достоинства и недостатки, знаю "правила хорошего тона", и не имею предрассудков в аккумуляции всего при принятии решений.

Тогда довольно странно слышать от тебя что ты goto в прод не коммитил. :scratch:

Цитата Qraizer @
Если я увижу, что goto конкретно вот тут не проявляет своих отрицательных сторон, но в сравнении с другими средствами проявляет положительные, заюзаю и не поморщусь.

Если бы у бабушки были яйца, то она была бы дедушкой. Мне видится что это из той же оперы. Я могу тебе сказать ровно то же самое. Вот зуб даю, если я увижу, что goto конкретно вот тут не проявляет своих отрицательных сторон, но в сравнении с другими средствами проявляет положительные, заюзаю и не поморщусь, но пока у меня таких ситуаций не было. А у тебя были? Я имею ввиду не на велосипедах? И да я читать умею. Знаю что не были. Ну так тогда о чем речь ? :D

Цитата Qraizer @
И это справедливо для любых других средств, той же рекурсии, например. Или не дай бог switch().

Конечно.

Цитата Qraizer @
Ну и если некий код вызывает вопросы типа "нахрена так", то это не означает автоматически, что он плохой. Возможно, были причины написать именно так, которых мы не знаем. Другое дело, чтобы из-за этого "нахрена" коду плохо не стало. Вот на это надо смотреть. Ну так и не стало же. Сколько ссылок ты не давал, столько раз я и приходил к выводу, что мол, да, странно, но вот так тоже нормально, плохих последствий не имеет.

Конечно не означает. Но ты ведь задумаешься - а можно ли избавится от этого и как? Или не будешь задумываться? Если ты не будешь задумываться - значит ты стороник goto. А если задумаешься, значит - ты такой же противник как и я. Но судя по тому что в прод ты не припомнишь чтоб goto коммитил, я могу сделать вывод, что ты либо не сталкивался с таким, либо все таки задавался вопросом - "нахрена так"? "А могу я по другому сделать?" И судя по всему - всегда получал ответ - "Да, я могу сделать по другому.". Ну разве не так получается?

Цитата Qraizer @
Кстати вот, а почему у тебя switch() не вызывает отторжения?

Незнаю :-? Но скажу честно, я не припомню когда я использовал switch в последний раз. Хотя могу сказать наверняка - я точно его использовал несколько раз.

Цитата Qraizer @
Ну, автором был я. Восстанавливал код по памяти, изначально это был такой же полусинтетический пример для другого ресурса, давно почившего лет за 10 до этого. А тот в свою очередь являлся выжимкой некой вполне практической задачи, писавшейся для однозадачной DOS. Код сохранения/восстановления внедрялся в уже готовую программу, когда выяснилось, что программа будет работать слишком долго, и не факт, что всё это время комп не понадобится для более срочных задач. Почитай, более 20-и лет назад, откуда я помню-то истоки.

Ну если это было давно по молодости - то тогда это многое объясняет и все становится понятно, и я претензий никаких не имею. Я по молодости так же не гнушался использовать макросы вместо констант, и goto, и писал еще похуже трешаки. Я просто думал что этот код ты выдрал с прода, для демонстрации возможностей goto. Ну в принципе даже по той первой теме, из за этого кода срач вышел на десяток страниц помница. Не каждый так сможет написать. :D

Цитата Qraizer @
Ну, это не ко мне. Бинарный ввод/вывод у потоков диктует char*, что тут сделаешь.

Ну меня в основном запутало именно сохранение состояния. Я поначалу думал что оно играет какую то важную роль в алгоритме и является неотъемлемой частью цикла. Пока не вынес это в отдельную функцию.
Еще очень смутили конструкции типа
ExpandedWrap disabled
    ok = ok && read/write file

Но по началу я не придал им значения, пока не присмотрелся пристально, а что же там происходит, и нафига именно вот так.
Сообщение отредактировано: KILLER -
Цитата KILLER @
__finally говно еще то, по крайней мере в С++. Я так понимаю - это уже из области SEH исключений? Я сталкивался с этим, и очень плотно сталкивался, и матюкался и плевался. Потому что когда ты попадаешь в этот блок - фрейм стека теряется напрочь, и ты ничего не можешь сделать, вернее можешь - но это все нужно делать вручную, чтоб сохранить фрейм стека. В Си - возможно это благо и чудо, я не буду спорить, потому как в Си я с этим не работал, но там нет и классов. А я с этой херней работал именно в С++ и с классами. Правда было это довольно давненько, лет 5 назад, а то и 8. Деталей я не помню сейчас. Но! вся эта шняга типа __finally нужна для конкретных вещей. А goto - не нужен для конкретных вещей. И если вылетит Access Violation - __finally в принципе может как то помочь, а вот goto - нет. Потому что это два разных уровня взаимодействия с программой.
В таком случае, как обычно в таких случаях и советуется, причём далеко не только мной, советую изучить матчасть по SEH. Сейчас, увы, Wolfenstein II ждёт, но попозже я накатаю кратенюсенький ликбез. Пока и коротко – C++EH в MS-ных компилерах по WinAPI основан как раз на SEH, так что любая твоя программа с исключениями под капотом юзает SEH на полную катушку. И даже больше: SEH нередко задействуется и при return, и при continue и break, и при longjmp(), и – да ты и так догадался – при goto. Причём я сейчас не о C++.

Добавлено
Цитата KILLER @
Я могу тебе сказать ровно то же самое.
Ну вот я которую страницу и не понимаю, объчём сыръбор.
Цитата KILLER @
Но ты ведь задумаешься - а можно ли избавится от этого и как? Или не будешь задумываться? Если ты не будешь задумываться - значит ты стороник goto.
Задумаюсь. Прикину стоимость редизайна, поставлю рядом величину его профита и ...тут может случиться по-разному. Скорее всего, если код написан на GWBasic в стиле соседа Пупкина, редизайн окупится, если же ты имеешь в виду код, подобный на который ты приводил ссылки, то запросто может и не окупиться.
Я не сторонник или несторонник goto, я сторонник структурных решений и несторонник неструктурных. Современные языки предлагают полный спектр для реализации структурных решений, поэтому места для goto в программах практически не остаётся. Реалии однако таковы, что структурные решения не всегда бывают оправданными своей стоимостью реализации. Но, слава богу, весьма нечасто, и это хорошо. Для неструктурных решений многие языки предлагают только goto. Иногда ещё исключения подойдут. Глупо не пользоваться нужной фичей, когда она есть, и городить вместо это структурный костыль. Это не лучше, чем пытаться заменить множественное наследование агрегацией.
Цитата KILLER @
Я по молодости так же не гнушался использовать макросы вместо констант, и goto, и писал еще похуже трешаки.
Та какая разница. По молодости я изначально не подумал, что понадобится сохранять/восстанавливать состояние? Так я и сейчас могу об этом не подумать. Заюзал бы я сейчас в подобной ситуации goto? Когда код с ним написан за пять минут, не нуждается в отладке, прост, понятен и производителен? Обязательно.
Сообщение отредактировано: Qraizer -
Одни с годами умнеют, другие становятся старше.
Цитата Qraizer @
Сейчас, увы, Wolfenstein II ждёт, но попозже я накатаю кратенюсенький ликбез.
Начал тут обдумывать, что писать, и понял, что кратенюсенько не получится. Ладно, тогда пока просто перепишу первый пример на SEH.
ExpandedWrap disabled
    int copyFile(const char* src, const char* dst)
    {
      void *buf = NULL;
      FILE *inF = NULL;
      FILE *ouF = NULL;
      size_t readed, written;
      int    res = 0;
     
      __try
      {
        buf = malloc(BUF_SIZE);
        inF = fopen(src, "rb");
        ouF = fopen(dst, "wb");
     
        if (buf == NULL) __leave;
        if (inF == NULL) __leave;
        if (ouF == NULL) __leave;
     
        readed = fread(buf, 1, BUF_SIZE, inF);
        while (!feof(inF) || readed != 0)
        {
          written = fwrite(buf, 1, readed, ouF);
          if (written != readed) __leave;
          readed = fread(buf, 1, BUF_SIZE, inF);
        }
        res = 1;
      }
      __finally
      {
        if (ouF != NULL) fclose(ouF);
        if (inF != NULL) fclose(inF);
        if (buf != NULL) free(buf);
      }
      return res;
    }
Думаю, тут и без ликбеза всё понятно. SEH штука классная. Её отсутствие в POSIX делает мне программинг в нём некомфортным.
Одни с годами умнеют, другие становятся старше.