Здравствуйте, MTD, Вы писали:
ARK>>Непонятно. Это все не нужно. GetIter не должен завершаться с ошибкой. MTD>Это почему? А если память, например, не удалось выделить?
Если память не удалось выделить, то это крах программы, исключения тут не помогут.
ARK>>HasNext и Next должны быть одним методом MoveNext MTD>На практике это неудобно, например, я не хочу сдвигать итератор, просто хочу проверить, что есть куда сдвигать.
Ну пусть будет, мне не жалко. Только не надо его тогда в пример приводить для придания многословности (или, если уж приводить, то в обоих примерах).
ARK>>для которого тоже нет резона возвращать ошибку. MTD>А MoveNext невалидному итератору? Ты уверен, что стоит так замаскировать баг?
Да, согласен, маскировать в данном случае нехорошо. Если брать обычные коды ошибок, то проверку следует сделать один раз после цикла:
for (Iter i : data)
{
X x;
if (i.Get(x))
{
...
}
}
if (data.IteratorCorrupted)
{
...
}
Если что-то гипотетическое в духе Раста, то сам цикл должен возвращать некий результат — ошибка или ОК.
Because that error right there? No compiler error, no warning, you lose. You just have to be trained well enough to watch for them and prevent them. Very insidious bugs if you don't know what you're doing. One of the design philosophies of C++ is speed over safety. The runtime check that would lead iterator invalidation to an exception instead of unspecified behavior is too expensive, in the view of C++ language designers.
отличный код. супер. реально. теперь попробуй его переделать на исключения. могу дать подсказку, в одних случаях наличие error ведёт сразу к возврату из функции ( это легко заменить на единственный try/catch ), а в других ( примерно с середины твоего кода ) error в некоторых случаях игнорируется, например здесь:
здесь любая строка может не отработать, но это игнорируется. Покажи теперь как это (это — весь твой код ) будет на исключениях, аххахаха (зловещий хохот ).
MTD>На досуге предлагаю написать итератор без исключений, с помощью конструктора без исключений создать объект с гарантией, что если объект создан то он в валидном состоянии и т.д.
с исключениями у тебя вся программа — одно сплошное невалидное состояние
class Frobber
{
private:
int m_NumberOfFrobs;
FrobManager m_FrobManager;
public:
void Frob()
{
m_NumberOfFrobs++;
m_FrobManager.HandleFrob(new FrobObject());
}
};
что если new FrobObject кинет исключение? m_NumberOfFrobs пушкин отревертит? а это очень простой пример. Собственно когда "обсасывалось уже сто раз" ты видимо пропустил такой момент, что исключения могут работать только при полной строгой гарантии исключений ( т.е. все методы — транзакционны ), но это бывает только в стране эльфоф и цветных пони.
Здравствуйте, MTD, Вы писали:
MTD>Это почему? А если память, например, не удалось выделить?
бросать исключение. это нарушение инварианта. поломанный assert короче говоря.
MTD>На практике это неудобно, например, я не хочу сдвигать итератор, просто хочу проверить, что есть куда сдвигать.
логика на исключениях? мне вас жаль (с)
MTD>А MoveNext невалидному итератору? Ты уверен, что стоит так замаскировать баг?
бросать исключение. это нарушение инварианта. поломанный assert короче говоря.
A> error = sAIPanelFlyoutMenu->AppendItem(fPanelFlyoutMenu, 1, ai::UnicodeString("First Item"));
A> error = sAIPanelFlyoutMenu->AppendItem(fPanelFlyoutMenu, 3, ai::UnicodeString("Third Item"));
A> error = sAIPanelFlyoutMenu->InsertItem(fPanelFlyoutMenu, 3, 2, ai::UnicodeString("Second Item"));
A> error = sAIPanelFlyoutMenu->InsertSeparator(fPanelFlyoutMenu, 3, 5);
A> error = sAIPanelFlyoutMenu->AppendItem(fPanelFlyoutMenu, 4, ai::UnicodeString("Fourth Item"));
A>
A>здесь любая строка может не отработать, но это игнорируется. Покажи теперь как это (это — весь твой код ) будет на исключениях, аххахаха (зловещий хохот ).
%% Для варианта 1 и 2 ниже
%% нам нужен список элементов и функция, их добавляющая
list_of_items() ->
["First Item", "Third Item", separator, "Fourth Item"].
add_to_menu(Item) ->
try
fly_out_menu:append_item(panel_flyout_menu, Item)
catch
_:Reason -> {error, Reason}
end.
%% ------------------------
%% Вариант 1
%% лопатим вручную
safe_add([], Errors) ->
case Errors of
[] -> ok;
_ -> %% обработали ошибки, если надо
end;
safe_add([Item|Rest], Errors) ->
case add_to_menu(Item) of
ok -> safe_add(Rest, Errors);
{error, Reason} = safe_add(Rest, [Reason | Errors])
end.
%% и дальше в коде где-то
safe_add(list_of_items()).
%% ------------------------
%% Вариант 2
%% foldl
safe_add(Item, Errors) ->
case add_to_menu(Item) of
ok -> Errors;
{error, Reason} -> [Reason | Errors]
end.
%% где-то в коде
case lists:foldl(fun safe_add/2, [], list_of_items()) of
[] -> ok;
Errors -> %% обрабатываем все ошибки
end.
%% ------------------------
%% Вариант 3
%% Один в один код из Адоба
adobe_style_adъ() ->
% игнорируем ошибки
catch fly_out_menu:append_item(panel_flyout_menu, "First Item"),
catch fly_out_menu:append_item(panel_flyout_menu, "Third Item"),
catch fly_out_menu:append_item(panel_flyout_menu, "Second Item"),
catch fly_out_menu:append_item(panel_flyout_menu, separator),
% не игнорируем ошибки
fly_out_menu:append_item(panel_flyout_menu, "First Item").
%% где-то дальше в коде
try
adobe_style_adъ()
catch
_:Reason -> %обработали ошибку
Здравствуйте, antropolog, Вы писали:
A>да покажите же наконец эту кучу бойлерплейт кода хоть в одном реальном проекте, и заодно покажите как бы это классно выглядело с исключениями, посмеёмся всеми шрёдерами
Посмотри любой COM-сервис и его аналог на Дотнете или Яве. Я вдоволь насмотрелся на код для MS VS написанный на С++ и на то как в нем теряется обработка ошибок просто поту что кому-то было в лом ее протаскивать. Аналогичный код на C# в разы понятнее и проще.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, kaa.python, Вы писали:
KP>Ну вообще-то, в 21 веке, более-менее квалифицированные C++ программисты такого трэша не пишут и пользуются умными указателями
Увы не все из более-меенее квалифицированных не знакомы даже с shared_ptr, а про unique_ptr и про другие тем более не знают.
Так что проблема действительно имеет место быть.
Вот если бы компилятор не компилировал явный 'new'/malloc и подобное , тогда было бы другое дело.
Здравствуйте, _NN_, Вы писали:
_NN>Здравствуйте, kaa.python, Вы писали:
KP>>Ну вообще-то, в 21 веке, более-менее квалифицированные C++ программисты такого трэша не пишут и пользуются умными указателями _NN>Увы не все из более-меенее квалифицированных не знакомы даже с shared_ptr, а про unique_ptr и про другие тем более не знают. _NN>Так что проблема действительно имеет место быть. _NN>Вот если бы компилятор не компилировал явный 'new'/malloc и подобное , тогда было бы другое дело.
shared_ptr и unique_ptr — это еще ладно, это либо буст, либо C++11
Но auto_ptr-то сто лет как есть и вполне прилично свою задачу по убийству чего не нужно решает, во всяких фабриках и т.п.
Здравствуйте, jazzer, Вы писали:
J>shared_ptr и unique_ptr — это еще ладно, это либо буст, либо C++11 J>Но auto_ptr-то сто лет как есть и вполне прилично свою задачу по убийству чего не нужно решает, во всяких фабриках и т.п.
Это конечно так, но основой массе людей нет времени или желания разбираться в тонкостях C++.
К счастью большинство кода на C# и поэтому проблем этого плана меньше
Здравствуйте, AlexRK, Вы писали:
ARK>Здравствуйте, MTD, Вы писали:
ARK>>>Непонятно. Это все не нужно. GetIter не должен завершаться с ошибкой. MTD>>Это почему? А если память, например, не удалось выделить?
ARK>Если память не удалось выделить, то это крах программы, исключения тут не помогут.
Здравствуйте, _NN_, Вы писали:
_NN>Здравствуйте, jazzer, Вы писали:
J>>shared_ptr и unique_ptr — это еще ладно, это либо буст, либо C++11 J>>Но auto_ptr-то сто лет как есть и вполне прилично свою задачу по убийству чего не нужно решает, во всяких фабриках и т.п. _NN>Это конечно так, но основой массе людей нет времени или желания разбираться в тонкостях C++.
В смысле, что 95% программеров — индусы ленивые идиоты, нежелающие изучать собственный инструмент? Ну да, для них тогда нужен инструмент с хорошей защитой от дурака, с философией "пиши как хочешь и ни о чем не беспокойся, память больше не ресурс (с) и gc за всем приберет".
_NN>К счастью большинство кода на C# и поэтому проблем этого плана меньше
Тогда уж Java.
auto_ptr в С++ был, когда шарпа еще и в проекте не было (ну или как раз в проекте, судя по Вики). И во всех "библиях" типа майерса, саттера и т.п. (а ведь у них сайты/блоги были, не только бумажные книги) и факах самого Бьярне он активно продвигался (вместе с самим принципом RAII)
Здравствуйте, _NN_, Вы писали:
_NN>Увы не все из более-меенее квалифицированных не знакомы даже с shared_ptr, а про unique_ptr и про другие тем более не знают. _NN>Так что проблема действительно имеет место быть. _NN>Вот если бы компилятор не компилировал явный 'new'/malloc и подобное , тогда было бы другое дело.
Можно сделать отдельный верификатор запрещающий их везде кроме специально отведённого места. Например на базе Clang AST Matchers. Да даже grep'а хватит(если кто попробует обхитрить grep — то будет расцениваться как диверсия).
Здравствуйте, jazzer, Вы писали:
MTD>>>Это почему? А если память, например, не удалось выделить? ARK>>Если память не удалось выделить, то это крах программы, исключения тут не помогут. J>
Ну приблизительно по таким вот причинам Windows регулярно в синий экран и выпадало ведь.
А что ещё делать? Вокруг одни коды ошибок, исключений вдобавок нет, ещё и память не выделяеться и бац!
Как синий экран отрисовывали-то — загадка. Да что там синий экран. Вот Windows 8 — вместо синего экрана — красюсюшки рисует. Магия.
Здравствуйте, _NN_, Вы писали:
_NN>Увы не все из более-меенее квалифицированных не знакомы даже с shared_ptr, а про unique_ptr и про другие тем более не знают.
Просто они не квалифицированные C++ разработчики, не более того.
_NN>Так что проблема действительно имеет место быть.
Проблема отсутствия квалифицированных специалистов, разве что.
Здравствуйте, antropolog, Вы писали:
A>что если new FrobObject кинет исключение? m_NumberOfFrobs пушкин отревертит? а это очень простой пример. Собственно когда "обсасывалось уже сто раз" ты видимо пропустил такой момент, что исключения могут работать только при полной строгой гарантии исключений ( т.е. все методы — транзакционны ), но это бывает только в стране эльфоф и цветных пони.
Здравствуйте, fddima, Вы писали:
F>Здравствуйте, jazzer, Вы писали:
MTD>>>>Это почему? А если память, например, не удалось выделить? ARK>>>Если память не удалось выделить, то это крах программы, исключения тут не помогут. J>> F> Ну приблизительно по таким вот причинам Windows регулярно в синий экран и выпадало ведь. F> А что ещё делать? Вокруг одни коды ошибок, исключений вдобавок нет, ещё и память не выделяеться и бац! F> Как синий экран отрисовывали-то — загадка. Да что там синий экран. Вот Windows 8 — вместо синего экрана — красюсюшки рисует. Магия.
Это ты еще забыл, что "память больше не ресурс" (с)
Здравствуйте, antropolog, Вы писали:
A>что если new FrobObject кинет исключение? m_NumberOfFrobs пушкин отревертит?
Зачем? m_NumberOfFrobs считает количество попыток, в т.ч. и проваленных, так что ничего отворачивать не надо. Ну или у тебя логическая ошибка, если ты от этого счетчика хотел что-то другое. Например, удачные попытки нужно считать после того, как они удались, а считать количество FrobObject должен FrobManager, если он ими владеет а не просто обрабатывает и сразу удаляет.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Здравствуйте, antropolog, Вы писали:
A>отличный код. супер. реально. теперь попробуй его переделать на исключения. могу дать подсказку, в одних случаях наличие error ведёт сразу к возврату из функции ( это легко заменить на единственный try/catch ), а в других ( примерно с середины твоего кода ) error в некоторых случаях игнорируется, например здесь:
Исключения — это исключительные ситуации игнорирование которых делает дальнейшую работу бессмысленной, это если ты вдруг не в курсе.
A>с исключениями у тебя вся программа — одно сплошное невалидное состояние A>
A>class Frobber
A>{
A>private:
A> int m_NumberOfFrobs;
A> FrobManager m_FrobManager;
A>public:
A> int Frob()
A> {
A> m_NumberOfFrobs++;
FrobObject* f = NULL;
if (!CreateFrobObject(f)) return -1; // Чем это лучше?
A> m_FrobManager.HandleFrob(f);
A> }
A>};
A>
Все-таки смешные вы, уже второй раз пишете говнокод, который будет говнокодом хоть с кодами ошибок, хоть с исключениями и считаете, что это что-то должно доказать.
Здравствуйте, antropolog, Вы писали:
A>бросать исключение.
Не понял, ты же кричал, что код с исключениями — УГ по определению.
MTD>>На практике это неудобно, например, я не хочу сдвигать итератор, просто хочу проверить, что есть куда сдвигать. A>логика на исключениях? мне вас жаль (с)
Здравствуйте, jazzer, Вы писали:
J>Каким образом? Или речь прерывании потока каким-нибудь хакерством за пределами языка, типа KillThread какой-нибудь? Ну тогда да, против лома нет приема.
А что у вас вместо лома? В managed environment даже при аборте потока есть шанс отработать хэндлеры и прибрать за собой ресурсы. В С++ такого просто вообще нет. J> С тем же успехом можно прибить поток, в котором крутится сам сборщик мусора.
Фантазии оставьте. Даже если вы сумеете найти хэндл GC-потока и прибить, то среда просто перезапустит его.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, jazzer, Вы писали: J>А Синклер вон до сих пор, в 2015, спустя 16 лет (!!!), какой-то трэш на эту тему пишет
В прошлый раз, когда поднималась тема C++, в первом же взятом открытом проекте мы нашли всё подряд — и выделение на голых malloc (хотя "конечно же все серъёзные проекты используют пулы, арены, и прочие продвинутые стратегии выделения/очистки), и raw pointers, и вызовы delete.
Но это да, Синклер виноват в том, что программисты С++ пишут вовсе не так, как о себе думают.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.