Size: a a a

2020 July 29

m

magras in pro.cxx
На самом деле главная проблема в том, что я до сих пор не видел нормальных сравнений производительности. Часто встречаются фразы "мы включили поддержку исключений в коде написанном на кодах возврата и стало хуже", но такие замеры бесполезны. Поэтому все споры исключения vs коды возврата сводятся к экспертным оценкам и религии. =(
источник

O

Ofee in pro.cxx
magras
На самом деле главная проблема в том, что я до сих пор не видел нормальных сравнений производительности. Часто встречаются фразы "мы включили поддержку исключений в коде написанном на кодах возврата и стало хуже", но такие замеры бесполезны. Поэтому все споры исключения vs коды возврата сводятся к экспертным оценкам и религии. =(
Я, честно говоря, не понимаю, как обсуждение вкусовых предпочтений "монады vs исключения" дошло таки до сравнения производительности возврата монад и бросания исключений, но думаю, что самый правильный вывод — выбор чаще обосновывается либо привычками, либо чувством прекрасного, чем любыми другими аргументами

И одна из проблем тут — ужасное неудобство комбинирования нескольких вариантов и отсутствия возможности сделать выбор в пользу одного или другого пользователем (какой бы то ни было) библиотеки. Ещё больший ужас начинается, когда несколько разных библиотек используют разные механизмы обработки ошибок.

Поэтому единственный способ пользователей повлиять на библиотеки, которыми они пользуются — проповедовать свою религию и делать её популярнее :)
источник

m

magras in pro.cxx
Ofee
Я, честно говоря, не понимаю, как обсуждение вкусовых предпочтений "монады vs исключения" дошло таки до сравнения производительности возврата монад и бросания исключений, но думаю, что самый правильный вывод — выбор чаще обосновывается либо привычками, либо чувством прекрасного, чем любыми другими аргументами

И одна из проблем тут — ужасное неудобство комбинирования нескольких вариантов и отсутствия возможности сделать выбор в пользу одного или другого пользователем (какой бы то ни было) библиотеки. Ещё больший ужас начинается, когда несколько разных библиотек используют разные механизмы обработки ошибок.

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

ГH

Гласси Hudobin in pro.cxx
...Теперь мне захотелось переделать backtrace, чтобы работал без выделений памяти, без бросания исключений и без макросов.
источник

ПК

Побитый Кирпич... in pro.cxx
Гласси Hudobin
...Теперь мне захотелось переделать backtrace, чтобы работал без выделений памяти, без бросания исключений и без макросов.
backtrace с исключениями слабо связан
источник

O

Ofee in pro.cxx
magras
На всякий случай еще раз уточню, что под кодами возврата я имею в виду все механизмы обработки ошибок кроме исключений, потому что с точки зрения сгенерированного асма они примерно равнозначны.
Да, я понял, на всякий случай отредактировал сообщение, чтобы не воспринималось так неоднозначно

Есть ещё одна интересная бумага. В разделе 4.2. Proliferation of "two-API" libraries есть ещё одна мысль — мы, будучи авторами библиотеки, можем предоставить пользователю оба способа обработки наших ошибок, вот строка из примера:
fs::resize_file(p, 1000).or_throw();
Т.е. сделав интерфейс библиотеки монадическим, мы можем обеспечить пользователю оба возможных инструмента, а наоборот я себе этого не представляю.

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

m

magras in pro.cxx
Ofee
Да, я понял, на всякий случай отредактировал сообщение, чтобы не воспринималось так неоднозначно

Есть ещё одна интересная бумага. В разделе 4.2. Proliferation of "two-API" libraries есть ещё одна мысль — мы, будучи авторами библиотеки, можем предоставить пользователю оба способа обработки наших ошибок, вот строка из примера:
fs::resize_file(p, 1000).or_throw();
Т.е. сделав интерфейс библиотеки монадическим, мы можем обеспечить пользователю оба возможных инструмента, а наоборот я себе этого не представляю.

И  интереснее то, что внутренняя логика библиотеки при этом может быть написана хоть на исключениях, хоть на монадах, пользователь получит всё-равно нужный ему интерфейс. Мне кажется, такой интерфейс был бы довольно выразительным и удобным (вне контекста производительности)
Наоборот это делается через враппер вида try { return fs::resize_file(p, 1000); } catch(...) { return error; }. Проблема в том, что в обоих подходах будут расходы на конвертацию. Но да, публичные интерфейсы это боль в плане обработки ошибок.
источник

O

Ofee in pro.cxx
magras
Наоборот это делается через враппер вида try { return fs::resize_file(p, 1000); } catch(...) { return error; }. Проблема в том, что в обоих подходах будут расходы на конвертацию. Но да, публичные интерфейсы это боль в плане обработки ошибок.
Вот только в первом случае за нас это сделал автор библиотеки, а во втором, на мой взгляд, мы имеем крайне некрасивый враппер (нет, правда, сомневаюсь, что кто-то назовёт этот код прекрасным), который либо придётся написать самим, либо его напишет автор библиотеки, но мы опять столкнёмся с проблемой, что у нас будут в одном пространстве имён разные перегрузки для одного и того же.
И их возможно будет случайно перепутать, получив крайне неприятные последствия:
* вызвать не бросающую версию вместо бросающей и пропустить ошибку
* в случае, когда просто хотим игнорировать ошибку, можем вызвать бросающую вместо не бросающей и приложение упадёт
источник

m

magras in pro.cxx
Ofee
Вот только в первом случае за нас это сделал автор библиотеки, а во втором, на мой взгляд, мы имеем крайне некрасивый враппер (нет, правда, сомневаюсь, что кто-то назовёт этот код прекрасным), который либо придётся написать самим, либо его напишет автор библиотеки, но мы опять столкнёмся с проблемой, что у нас будут в одном пространстве имён разные перегрузки для одного и того же.
И их возможно будет случайно перепутать, получив крайне неприятные последствия:
* вызвать не бросающую версию вместо бросающей и пропустить ошибку
* в случае, когда просто хотим игнорировать ошибку, можем вызвать бросающую вместо не бросающей и приложение упадёт
Можно и обобщенный враппер написать:
template <class F, class T, class E, class >
std::expected<T, E> to_expected(F&& f) {
 try { return f(); }
 catch(const E& e) { return {e}; }
}

to_expected([]{ fs::resize_file(p, 1000); });

То что код некрасивый, я согласен. И я считаю, что необходимость преобразовывать exception в expected это ошибка проектирования библиотеки. На мой взгляд есть два варианта решения:
1) использовать expected
2) использовать исключения и добавить функцию для проверки precondition (например get_free_space)

При этом второе решение не подходит в данном случае, так как фс это общий ресурс и проверка свободного места одну миллисекунду назад не гарантирует что сейчас место под ресайз все еще есть.
источник

m

magras in pro.cxx
Но при этом, если ошибка возникнет из-за сбоя жесткого диска, я бы спокойно кидал исключение. Это нельзя проверить заранее и количество кода, который будет обрабатывать такую ошибку исчезающе мало.
источник

O

Ofee in pro.cxx
magras
Но при этом, если ошибка возникнет из-за сбоя жесткого диска, я бы спокойно кидал исключение. Это нельзя проверить заранее и количество кода, который будет обрабатывать такую ошибку исчезающе мало.
Да, я думаю, что согласен по всем пунктам)
источник

ПК

Побитый Кирпич... in pro.cxx
magras
Можно и обобщенный враппер написать:
template <class F, class T, class E, class >
std::expected<T, E> to_expected(F&& f) {
 try { return f(); }
 catch(const E& e) { return {e}; }
}

to_expected([]{ fs::resize_file(p, 1000); });

То что код некрасивый, я согласен. И я считаю, что необходимость преобразовывать exception в expected это ошибка проектирования библиотеки. На мой взгляд есть два варианта решения:
1) использовать expected
2) использовать исключения и добавить функцию для проверки precondition (например get_free_space)

При этом второе решение не подходит в данном случае, так как фс это общий ресурс и проверка свободного места одну миллисекунду назад не гарантирует что сейчас место под ресайз все еще есть.
нехватка места сама собой зафейлится внутрях
источник

AD

Apache DOG™ in pro.cxx
А вот ещё вопросик, какая принципиальная проблема в С++ мешает возвращать несколько результатов из функции?
источник

O

Ofee in pro.cxx
Apache DOG™
А вот ещё вопросик, какая принципиальная проблема в С++ мешает возвращать несколько результатов из функции?
Никакой, в общем-то, благодаря появлению structured binding
Да, пожалуй, присоединюсь к вопросу ниже, не уверен, что понял суть правильно
источник

D

Dmitriy in pro.cxx
Apache DOG™
А вот ещё вопросик, какая принципиальная проблема в С++ мешает возвращать несколько результатов из функции?
Несколько результатов разных неполиморфных типов без использования variant?
источник

AD

Apache DOG™ in pro.cxx
Dmitriy
Несколько результатов разных неполиморфных типов без использования variant?
(int int) divide(int a, int b)
источник

AD

Apache DOG™ in pro.cxx
например
источник

O

Ofee in pro.cxx
Apache DOG™
например
structured binding:

std::pair<int, int> divide(int a, int b);
// ...
auto [x, y] = divide(42, 0);
источник

AD

Apache DOG™ in pro.cxx
но это через таплы
источник

O

Ofee in pro.cxx
Apache DOG™
но это через таплы
А в чём принципиальная разница-то, кроме усложнения ABI?)
источник