RTTI и исключения сильно упрощают код и увеличивают его надежность.
Про RTTI анонимус выше написал. С исключениями всё несколько сложнее: в C++ нет возможности проверить во время компиляции поймал ли я все возможные исключения или что-то пролетело мимо. Разве что catch(...), но у этого подхода тоже есть недостатки.
RTTI и, в частности, dynamic_cast, очень сильно спасают при необходимости делать downcast-инги. А в больших программах с развесистым ООП это делать приходится. И выскочившее из dynamic_cast-а исключение намного лучше, чем обращение по битому указателю.
С исключениями всё несколько сложнее: в C++ нет возможности проверить во время компиляции поймал ли я все возможные исключения или что-то пролетело мимо. Разве что catch(...), но у этого подхода тоже есть недостатки.
Не нужно рассказывать мне сказки и пересказывать городские легенды.
Возможность проверить во время компиляции... Это даже в Java с их checked exceptions не работает. В современном C++ есть noexcept.
RTTI и исключения сильно упрощают код и увеличивают его надежность
Ну расскажи мозильщикам об этом, а то мужики страдают. Может что-то в консерватории не так, раз в любом крупном проекте скукоживают Мощный Высокоуровневый ЯП до си с классами.
раз в любом крупном проекте скукоживают Мощный Высокоуровневый ЯП до си с классами.
Не в любом. Посмотрите хотя бы на разработки Facebook-а. Это во-первых.
Во вторых, правильнее было бы сказать «скукоживали», поскольку качество C++ных компиляторов во времена оные оставляло желать лучшего. Сейчас смысл «скукоживать» остался только в очень узких областях (вроде тех, что требуют использования стандартов типа MISRA-C++ и похожих на него).
Практика показала, что этот контроль не нужен, чтобы нормально писать код с исключениями.
Чья практика? Ссылку! Ссылку!
От того, что эта библиотека бросает int в качестве исключения, не спасет.
Тебе не кажется, что эта штука несколько бесполезна? Как и nothrow. Нормальная система модулей, включающая информацию об исключениях в описание модулей, могла бы что-то исправить, но в C++ её нет.
обрабатывается лишь то, с чем можно справится;
А если нужно справиться со всем?
код пишется так, чтобы обеспечивать хотя бы базовую гарантию безопасности исключений;
Хотя бы базовую, ага.
места, которые не должны бросать исключения, помечаются как noexcept. Соответственно, в run-time об этом можно не думать.
Как ты выше написал, от throw 123 в кишках левой библиотеки noexcept не спасёт, что делает его немного бесполезным. Смотри выше.
Это кстати ещё одна проблема C++: написать один только парсер для него - уже подвиг.
А за IDE, которая покажет полные сигнатуры, включая тип возвращаемого значения вот какого-нибудь такого кода
template<template class <T, A> C, typename E>
decltype(auto) f(C&& c, const E& e)
{
return C<T, A>{e};
}
нужно воздвигать памятник при жизни :-) Гг :-)
Да и в Интернете полно критики checked exceptions.
Я хочу, чтобы был единый контекст обсуждения, иначе есть риск взаимного недопонимания, потому и спрашиваю ссылки.
Тогда catch(...). Но покажите, как вы собираетесь справляться с _любым_ исключением.
Я не хочу справляться с _любым_ исключением. Я хочу, чтобы во время компиляции была доступна информация о том, какие исключения могут прилететь из данной функции, чтобы написать catch именно для них.
Меня, как пользователя языка, эта проблема мало волнует.
Зря, это напрямую влияет на качество инструментов разработки.
Тем более, что за последние года 3-4 ситуация, насколько я слышал, сильно изменилась.
С появлением C++11/14 ситуация стала только _хуже_, потому как синтаксис только усложнился. Конечно, всегда можно использовать парсер от clang, что все и делают, но завязываться на одну конкретную реализацию при наличии нескольких других - не слишком круто.
Я хочу, чтобы был единый контекст обсуждения, иначе есть риск взаимного недопонимания, потому и спрашиваю ссылки.
Ну тогда извините, за те 20 лет, что прошли после выхода Java в большой мир на тему того, что checked exceptions было сказано столько много, что искать сейчас конкретную ссылку на конкретную статью смысла не вижу.
Имхо, достаточно даже факта того, что в самой Java есть RuntimeException, если не ошибаюсь, которое может выскочить несмотря на все checked exceptions. И, следовательно, код на Java нужно писать оглядываясь на то, что из некого метода f() может выскочить не только те исключения, которое перечислены у него в throws.
Я не хочу... Я хочу
Ну что за подход? Хочу, не хочу, опять хочу.
Вот в C++ вот так. Нет декларации списка исключений. Это ведет к несколько другому подходу к написанию кода. Если функция f не noexcept, значит может бросить любое исключение. Значит то, что написано вокруг f должно быть написано так, чтобы любое выскочившее исключение не привело к порче данных.
Все. Вот так просто.
Хотя прийти к этому не просто. И это гораздо более серьезная проблема, чем сложность грамматики языка C++.
Сложный высокопроизводительный софт, как правило инфраструктурный, но не обязательно: GCC, clang/LLVM, HHVM, MSSQL ...
Настолько узкая специфическая ниша, что совсем не вижу смысла перетирать С++ на лоре. То есть лоровцев на пушечный выстрел к таким делам не подпустят, да и остальных рашкованов тоже. Для нас C++ это поддержка чудовищного говнолегаси из 90-х или хеловорды на кюте (еще более бессмысленное занятие). Хотя почитать лор, так тут такие гуру плюсов, что разработчики движка мозиллы нервно курят в сторонке.
Для того, чтобы обозначать места, в которых исключений быть не должно. Ну а если все-таки что-то бросается, то все, туши свет и сливай воду.
Например, операция swap. На том, что она не бросает исключений построено очень многое. Если же эта гарантия нарушается, то смысла продолжать работать нет. Поэтому методы/функции вроде swap помечаются noexcept.
Ну тогда извините, за те 20 лет, что прошли после выхода Java в большой мир на тему того, что checked exceptions было сказано столько много, что искать сейчас конкретную ссылку на конкретную статью смысла не вижу.
Моё быстрое гугление выдало в основном статьи в духе «это используют неправильно, это слишком сложно» и т.п. Поэтому я и просил технические аргументы против подобного подхода.
Ну что за подход? Хочу, не хочу, опять хочу.
Это всё, что ты можешь сказать?
Если функция f не noexcept, значит может бросить любое исключение. Значит то, что написано вокруг f должно быть написано так, чтобы любое выскочившее исключение не привело к порче данных.
Звучит воистину ужасно. Это, кстати, отлично объясняет почему Mozilla сотоварищи отказались от использования исключений.
Для того, чтобы обозначать места, в которых исключений быть не должно. Ну а если все-таки что-то бросается, то все, туши свет и сливай воду.
Например, операция swap. На том, что она не бросает исключений построено очень многое. Если же эта гарантия нарушается, то смысла продолжать работать нет. Поэтому методы/функции вроде swap помечаются noexcept.
Т.е. это попытка сделать градацию exception'ов? Типа некоторые exception'ы не exception'ы и их стоит обрабатывать? Т.е. по сути чуваки сделали return code'ы на exception'ах?
Поэтому я и просил технические аргументы против подобного подхода.
Боюсь, за такими списками вам нужно обращаться к авторам C#, Scala, Kotlin, Ceylon и т.д.
Это всё, что ты можешь сказать?
Это все, что я слышу с другой стороны.
Звучит воистину ужасно.
А вы попробуйте. Все не так страшно, как вам кажется.
Это, кстати, отлично объясняет почему Mozilla сотоварищи отказались от использования исключений.
Они от них отказались еще тогда, когда в некоторых компиляторах вообще нормальной поддержки исключений не было, а про noexcept в стандарте никто и не думал.
Боюсь, за такими списками вам нужно обращаться к авторам C#, Scala, Kotlin, Ceylon и т.д.
Я обращаюсь за ними к тебе, потому что ты о них тут упомянул.
А вы попробуйте. Все не так страшно, как вам кажется.
Я пробовал. Во всех проектах на C++, над которыми я работал, исключения либо не использовались вообще (-fno-exceptions), либо использовались когда нужно сдохнуть красиво, выплюнув максимальное количество информации о текущем состоянии. И решение о подобном подходе принимали люди, зачастую более умные и опытные чем я или ты.
Они от них отказались еще тогда, когда в некоторых компиляторах вообще нормальной поддержки исключений не было, а про noexcept в стандарте никто и не думал.
Это когда? В Webkit исключений нет, хотя он появился сравнительно недавно. В Qt исключений нет, хотя его код перетряхивают каждую мажорную версию, и в Qt5 исключения вполне могли бы появиться, если бы профит от них превышал расходы.
В Qt исключений нет, хотя его код перетряхивают каждую мажорную версию, и в Qt5 исключения вполне могли бы появиться, если бы профит от них превышал расходы.
Я об этом устал уже говорить :-) Сейчас тебе дадут ссылку на QException или как он называется, и будут кукарекать, что исключения в Qt есть :-) Гг :-)
Т.е. это попытка сделать градацию exception'ов? Типа некоторые exception'ы не exception'ы и их стоит обрабатывать? Т.е. по сути чуваки сделали return code'ы на exception'ах?
Нет.
Если функция помечена как noexcept, из нее можно не ждать исключения. Если же она все-таки исключение бросает, то сам run-time вызовет std::terminate и все приложение грохнется.
Это позволяет не парится лишний раз. Например, у нас есть класс с полями:
class person {
std::string m_name;
std::string m_surname;
...
};
который бы обеспечивал строгую гарантию безопасности исключений. Мы пишем что-то вроде:
void person::set(
not_null<const char *> name,
not_null<const char *> surname)
{
// Здесь может быть выброшено любое исключение.
// Но нам это не важно, т.к. происходит модификация
// временных объектов.
std::string new_name(name.get());
std::string new_surname(surname.get());
// А вот мы меняем значения и исключений быть не должно,
// в противном случае обеспечить строгую гарантию мы не сможем.
swap_values(new_name, new_surname);
}
void person::swap_values(
std::string & name, std::string & surname ) noexcept
{
m_name.swap(name);
m_surname.swap(name);
}
Вот как раз для специальной пометки методов вроде swap_values и предназначен noexcept.
Нет, не добавили!!! :-) Добавили лишь класс QException, а вот «Qt itself will not throw exceptions. Instead, error codes are used.» - см. http://doc.qt.io/qt-5/exceptionsafety.html
А в каком языке оно реально гарантируется? Checked исключения в джаве не спасут так как обычные тоже присутствуют.
Из более менее популярных - ни в каком. Idris двигают в этом направлении. В Haskell присутствует ExceptT (https://hackage.haskell.org/package/mtl-2.2.1/docs/Control-Monad-Except.html), что наиболее близко подходит к тому, что я хочу, но, к сожалению, можно всё равно невозбранно вызвать error откуда угодно. Это, в свою очередь, можно отлавливать с помощью Liquid Haskell, но он только появился и мало где используется.
Но это всё не является поводом не стремиться к лучшему, правда?
Я обращаюсь за ними к тебе, потому что ты о них тут упомянул.
Вот интересно, ссылку на что ты хочешь получить? Тебе нужно авторитетное мнение какого-то гуру?
Я пробовал.
Замечательно. Но. Вы пока еще не продемонстрировали, как будут выглядеть показанные выше по треду фрагменты кода, если переписать их без исключений.
Вот когда перепишете, будет лучше понятно о чем речь.
Если же кивать на личный опыт, то у меня были и периоды активного использования исключений, и периоды неиспользования, и опыт общения с компиляторами, которые их не поддерживали нормально. И ввязываться в С++ный проект без исключений у меня желания нет никакого.
Это когда?
Если говорить про Mozilla, то в середине 90-х полагаю. Из кодовая база оттуда ведет родословную.
Кстати, к спору про bad_alloc и Mac OS X, вот что написано на сайте Qt:
«Most desktop operating systems overcommit memory. This means that malloc() or operator new return a valid pointer, even though there is not enough memory available at allocation time. On such systems, no exception of type std::bad_alloc is thrown.»
QApplication app(argc, argv);
...
try {
app.exec();
} catch (const std::bad_alloc &) {
// clean up here, e.g. save the session
// and close all config files.
return 0; // exit the application
}
Если не про Mozilla, то у крупных компаний ситуация все равно похожая. Например, в Google, насколько я помню, C++ исключения запрещены. Но этому запрету уже фиг знает сколько лет, он широко известен стал лет 12-13 назад. И уже тогда речь шла о том, что исключений нет в старом коде, поэтому нечего их добавлять в новом. Так что все это следствие развития унаследованного кода, полагаю.