Re[10]: api design: return code or exception - formal criter
От: Юрий Жмеренецкий ICQ 380412032
Дата: 06.09.09 10:01
Оценка:
Здравствуйте, Николай Ивченков, Вы писали:

НИ>Юрий Жмеренецкий:


НИ>>>У меня есть подозрения, что тут всё же подразумеваются некие "слабые" концепции, выражающие общие требования к классу без предусловий выполнения этих требований. Т.е. класс удовлетворяет требованиям "слабой" концепции, если существует специфичный для него набор предусловий, при выполнении которых он поддерживает все операции в соответствии с указанной семантикой.


ЮЖ>>Для каких целей нужны такие концепции?


НИ>Для тех же, что и обычные концепции.

Для обычной концепции мне достаточно знать только ее контракт, для слабых — то же самое, плюс контракт 'реализатора'. Чем-то мне это напоминает dynamic_cast...

ЮЖ>>
НИ>/// \pre ???
НИ>template<class Lockable>
НИ>void f(Lockable& arg);

НИ>Данная функция, помимо принадлежности arg к Lockable, должна описывать характер использования arg (впрочем, тогда в ряде случаев можно вообще обойтись без упоминания о Lockable ). Исходя из этого описания пользователь функции должен сделать выводы о том, соблюдаются предусловия для его случая или нет.

Т.е. фактически предусловия пользователь должен выводить сам. В чуть более сложных случаях — вложенные вызовы, использование в f других таких концепций — это приведет к тому, что ему будет необходимо отследить весь путь выполнения (исходя из его случая). Пока я в этому вижу только минусы...

НИ>Фактически "слабая" концепция — это просто незавершённая концепция. Автор класса, формулируя конкретные предусловия, создаёт из неё завершённую концепцию (но без явного имени).


Чем-то напоминает CRTP. Я имел ввиду более 'худший' вариант: 'динамическую' концепцию, которая определена не статически для типа, а для значений, например после выполнения delete для указателя, последний перестает удовлетворять Assignable requirements. + не замкнутые относительно себя концепции.

ЮЖ>>что ты скажешь по поводу следующих двух вопросов?


НИ>1) Соответствует ли бустовой концепции Lockable класс std::mutex из N2914 — 30.4.1.1?

НИ>2) Может ли этот std::mutex быть использован для инстанцирования boost::unique_lock?

Если отвечать сразу — то нет в обоих случаях, хотя бы из-за типов исключений =) Если не принимать это во внимание — то, на первый взгляд, можно ответить да на оба вопроса. Но для точных ответов нужен более тщательный анализ. + некторые формулировки стандарта выглядят достаточно спорно, например

30.4.1/12 (mutext::lock)
Error conditions:
...
— resource_deadlock_would_occur — if the current thread already owns the mutex and is able
to detect it
.


30.4.3.2.2/4 (unique_lock::lock)
Error conditions:
...
— resource_deadlock_would_occur — if the current thread already owns the mutex (i.e., on entry,
owns is true)
.


Пследнее — это ни что иное как завуалированное предусловие, более того — формально, 30.4.3.2.2/2/3 делают невозможным возникновение ситуации c resource_deadlock_would_occur. Хотя я не исключаю что я что-то упустил.
Re[14]: api design: return code or exception - formal criter
От: Юрий Жмеренецкий ICQ 380412032
Дата: 06.09.09 10:01
Оценка: :)
Здравствуйте, Andrew S, Вы писали:

AS>Тем не менее. Представим, что реализация делает именно то, что и должна. Изначальный вопрос звучал так — почему тут исключение, а не assert? И то, и то может быть использовано как сигнализатор нарушения контракта.


Нарушение контракта всегда является дефектом, независимо от того с чьей стороны произошло нарушение (клиент/реализация). Возникновение исключения (вообще, не рассматривая unique_lock)- не является дефектом — это невозможность выполнения постусловий при выполненных предусловиях. Состояние объекта, как таковое, существует только в том случае если, его можно наблюдать (является observable). И вот как раз постусловия формулируются в виде предикатов, которые оперируют эти видимым состоянием. Ключевое свойство постусловий — их можно проверить (в принципе, но для этого нет необходимости) и на их основании клиент может сделать определенные выводы. Собственно сам по себе вызов функции необходим только для перевода объекта в состояние, в котором постусловия являются выполненными.

AS>В общем, предлагаю закругляться, никаких новых аргументов уже не появляется.


Ок. обсуждение unique_lock можно считать закрытым. Но у меня еще пара вопросов — считаете ли Вы, что например функция std::string::erase(iterator, iterator) должна проверять итераторы на валидность (и кидать исключение, в случае если дальнейшее выполнение прведет к порче 'состояния')?

Изменится или нет ответ на этот вопрос в таких случаях: 1) существует предусловие говорящее о том что передаваемые итераторы должны быть валидны (в как это формулируется для объекта string) 2) такое предусловие отсутствует.

Если в обоих случаях ответ — да, то Вы приверженец т.н. Defensive Programming Style, я же в свою очередь, нахожусь по другую сторону баррикад — второй случай дла меня неприемлим вообще (почти всегда), для первого — ответ нет. И, разумеется, этот выбор основан не на пустом месте.
Re[3]: api design: return code or exception - formal criteri
От: Vain Россия google.ru
Дата: 06.09.09 13:04
Оценка:
Здравствуйте, crable, Вы писали:

V>>К чему это всё скажите вы? А к тому что иногда поддержка исключений библиотекой приводит к образованию некоторого пользовательского болота, организованного недобросовестными программистами использующими библиотеку, из которого вам впоследствии будет трудно выбраться.

V>>Иногда лучше вообще не пользоваться исключениями и "заставлять" пользователя обрабатывать код возврата.
C>А мне показалось, что лучше не ставить ассерты перед throw и недобросовестеыми тут выглядят как раз программисты библиотеки, сделавшие это.
Тогда придётся перезапускать приложение с включёнными галками ловить исключения, что тоже не есть хорошо.
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[3]: api design: return code or exception - formal criteri
От: Vain Россия google.ru
Дата: 06.09.09 13:09
Оценка:
Здравствуйте, Erop, Вы писали:

V>>Иногда лучше вообще не пользоваться исключениями и "заставлять" пользователя обрабатывать код возврата.

E>IMHO, пользователей библиотеки, которые "развели болото" не удастся заставить верно обрабатывать коды возврата...
Для начало можно сделать коды возврата обязательными параметрами всех нужных функций.
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[15]: api design: return code or exception - formal criter
От: Andrew S Россия http://alchemy-lab.com
Дата: 06.09.09 14:53
Оценка:
AS>>В общем, предлагаю закругляться, никаких новых аргументов уже не появляется.

ЮЖ>Ок. обсуждение unique_lock можно считать закрытым. Но у меня еще пара вопросов — считаете ли Вы, что например функция std::string::erase(iterator, iterator) должна проверять итераторы на валидность (и кидать исключение, в случае если дальнейшее выполнение приведет к порче 'состояния')?


В debug time — да. В релизе — нет. Причины
1. Производительность.
2. Нарушение контракта не обеспечит нарушение контракта подчиненного объекта.

В случае unique_lock нарушение контракта ведет к нарушению контракта подчиненного объекта.

ЮЖ>Изменится или нет ответ на этот вопрос в таких случаях: 1) существует предусловие говорящее о том что передаваемые итераторы должны быть валидны (в как это формулируется для объекта string) 2) такое предусловие отсутствует.


Не изменится, в виду причин.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[11]: api design: return code or exception - formal criter
От: Николай Ивченков  
Дата: 06.09.09 15:15
Оценка:
Юрий Жмеренецкий:

ЮЖ>Для обычной концепции мне достаточно знать только ее контракт, для слабых — то же самое, плюс контракт 'реализатора'. Чем-то мне это напоминает dynamic_cast...


ЮЖ>>>
НИ>>/// \pre ???
НИ>>template<class Lockable>
НИ>>void f(Lockable& arg);

НИ>>Данная функция, помимо принадлежности arg к Lockable, должна описывать характер использования arg (впрочем, тогда в ряде случаев можно вообще обойтись без упоминания о Lockable ). Исходя из этого описания пользователь функции должен сделать выводы о том, соблюдаются предусловия для его случая или нет.

ЮЖ>Т.е. фактически предусловия пользователь должен выводить сам. В чуть более сложных случаях — вложенные вызовы, использование в f других таких концепций — это приведет к тому, что ему будет необходимо отследить весь путь выполнения (исходя из его случая). Пока я в этому вижу только минусы...


В N2914 вводятся "Mutex requirements", по сути являющиеся "слабой" концепцией. Эта концепция подразделяется на две: "non-recursive mutex" и "recursive mutex". std::unique_lock инстанцируется типом, соответствующим "слабой" концепции Mutex. Различие в использовании std::unique_lock, инстанцированного non-recursive mutex-ом, и std::unique_lock, инстанцированного recursive mutex-ом, проводится уже в описании его функций-членов:

explicit unique_lock(mutex_type& m);
Precondition: If mutex_type is not a recursive mutex the calling thread does not own the mutex.

По поводу повторного вызова lock у объекта типа std::unique_lock<T> мне пока неясно — то ли там undefined behavior, то ли генерация исключения.

НИ>>1) Соответствует ли бустовой концепции Lockable класс std::mutex из N2914 — 30.4.1.1?

НИ>>2) Может ли этот std::mutex быть использован для инстанцирования boost::unique_lock?

ЮЖ>Если отвечать сразу — то нет в обоих случаях, хотя бы из-за типов исключений =)


Ну, в принципе, можно рассмотреть некий MutexWrapper над std::mutex, где стандартные исключения будут транслироваться в бустовские, а всё остальное будет, как в std::mutex.

ЮЖ>Если не принимать это во внимание — то, на первый взгляд, можно ответить да на оба вопроса.


Ну, как же? У std::mutex::lock есть предусловие: эту функцию можно вызывать только если текущий поток не владеет данным мьютексом. Концепция Lockable (в Boost) такого предусловия не содержит.
Re[12]: api design: return code or exception - formal criter
От: Юрий Жмеренецкий ICQ 380412032
Дата: 06.09.09 16:24
Оценка:
Здравствуйте, Николай Ивченков, Вы писали:

НИ>В N2914 вводятся "Mutex requirements", по сути являющиеся "слабой" концепцией. Эта концепция подразделяется на две: "non-recursive mutex" и "recursive mutex".


Это две разных концепции. Упоминание "If mutex_type is not a recursive mutex" только подтверждает это. Фактически просто switch между двумя концепциями, а не использование одной.

ЮЖ>>Если не принимать это во внимание — то, на первый взгляд, можно ответить да на оба вопроса.


НИ>Ну, как же? У std::mutex::lock есть предусловие: эту функцию можно вызывать только если текущий поток не владеет данным мьютексом.


Где оно сформулировано? пока я вижу только "if a function does not specify any further preconditions, there will be no “Requires” paragraph."
Кроме того есть 17.6.3.11/1, и если ты говоришь что предусловие все же имеется, то должно ли оно удовлетворять 'стандартному' определению?
Плюс, аналога 17.6.3.11/1 для буста нет. Т.е. здесь возможна ситуация двух различных определений предусловий. Да и мое определение предусловий расходится с определением стадарта (они там, кстати, нарушили свой любимый zero-overhead principle).
Re[4]: api design: return code or exception - formal criteri
От: Erop Россия  
Дата: 06.09.09 19:59
Оценка:
Здравствуйте, Vain, Вы писали:

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


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

IMHO, качественный клинтский код -- это забота его авторов. Библиотека должна позволять писать качественный, и не должна мешать это делать или провоцировать на некачественный. Но бороться?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[13]: api design: return code or exception - formal criter
От: Николай Ивченков  
Дата: 06.09.09 20:05
Оценка:
Юрий Жмеренецкий:

НИ>>В N2914 вводятся "Mutex requirements", по сути являющиеся "слабой" концепцией. Эта концепция подразделяется на две: "non-recursive mutex" и "recursive mutex".


ЮЖ>Это две разных концепции. Упоминание "If mutex_type is not a recursive mutex" только подтверждает это. Фактически просто switch между двумя концепциями, а не использование одной.


Если говорить о типе, которым инстанцируется std::unique_lock, то тут используется именно одна "слабая" концепция Mutex. А то, что такому описанию std::unique_lock можно сопоставить некое эквивалентное по смыслу описание, выраженное через две концепции с более конкретизированными предусловиями — это уже другой вопрос.

ЮЖ>>>Если не принимать это во внимание — то, на первый взгляд, можно ответить да на оба вопроса.


НИ>>Ну, как же? У std::mutex::lock есть предусловие: эту функцию можно вызывать только если текущий поток не владеет данным мьютексом.


ЮЖ>Где оно сформулировано?


30.4.1.1/3:

The behavior of a program is undefined if:
[...]
— a thread that owns a mutex object calls lock() or try_lock() on that object

С точки зрения пользователя std::mutex нет никакой разницы между этим undefined behavior и undefined behavior, возникающим в результате несоблюдения условий, которые были бы явным образом специфицированы как предусловия. Т.е. фактически отсутствие владения мьютексом со стороны текущего потока можно считать предусловием для вызова lock.

ЮЖ>Плюс, аналога 17.6.3.11/1 для буста нет.


Если исходить из того же принципа (появление undefined behavior следует считать следствием нарушения предусловий), и если попытку повторного захвата boost::mutex считать приводящей к undefined behavior (у меня в тестовой программе попытка повторного захвата boost::mutex приводит к зависанию потока), то можно прийти к тем же выводам и относительно boost::mutex.

ЮЖ>они там, кстати, нарушили свой любимый zero-overhead principle.


Где именно?
Re[4]: api design: return code or exception - formal criteri
От: minorlogic Украина  
Дата: 06.09.09 20:23
Оценка: +1
Здравствуйте, Andrew S, Вы писали:

AS>На мой взгляд в этом случае именно что ассерты. Пользователь продолжает пользовать невалидный объект — значит ошибка в логике программы, а ошибку в логике надо по возможности отлавливать никак не в релизе. Эксепшены только в случае, если слой более низкого уровня вернул "плохую" ошибку. На плохой хендл, например, многие api так и сделают, так что автоматически без "лишней" рантайм проверки в релизе все будет выглядеть как надо.


Вы не путаете отладку программы с обработкой ошибок?

коды возврата и исключения это инструменты для обработки ошибок, assert макрос для отладки. Конечно их можно использовать не по назначению, но имеет ли смысл ?
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[2]: api design: return code or exception - formal criteri
От: minorlogic Украина  
Дата: 06.09.09 20:28
Оценка:
Здравствуйте, Vain, Вы писали:

V> После появились программисты библиотеки, которые поняли, что каждый раз включать галку в студии останавливаться на исключении в отладчике не катит и вставили ассерт перед самим throw.


Объясните подробнее пожалуйста этот кусок.
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[6]: api design: return code or exception - formal criteri
От: minorlogic Украина  
Дата: 06.09.09 20:42
Оценка: +2
Здравствуйте, Andrew S, Вы писали:

AS> Assert ровно такое же средство уведомления о нарушении контракта, как и исключение.


То же что и в предыдущем посте.

Исключение это средство ссобщить об ошибке рограммы, Assert об ошибке програмиста.

например в псевдокоде.
std::copy(It begin, It end, it2 begin2);

Существует задокументированный контракт что begin и end обязаны принадлежать одному множеству. В случае невыполнения этого контракта у результатом будет UB ( могло быть и исулючение, но это накладывает на реализацию жесткие ограничения).

В этом случае, хорошим тоном от разработчиков библиотеки, будет проверить и подсказать в отладочной сборке нарушение контракта. Но это не к коей мере не обработка ошибки, это только подсказка пользователям библиотеки о неправильном использовании.
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re: api design: return code or exception - formal criteria
От: minorlogic Украина  
Дата: 06.09.09 20:42
Оценка: +1
Небольшой офтоп.

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

пример результата выполнения.
bool fileExist(...);

Если эта функция вернет false это не означает что произошла ошибка и необходимо прервать выполнение программы.

пример ошибки выполнения.
bool fileExist(...);

Во время выполнения сетевой ресурс на который ссылается путь был отключен, это ошибка выполнения fileExist, и вполнен нормально в таком случае кинуть исключение.
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[14]: api design: return code or exception - formal criter
От: Юрий Жмеренецкий ICQ 380412032
Дата: 07.09.09 07:13
Оценка:
Здравствуйте, Николай Ивченков, Вы писали:

НИ>Если говорить о типе, которым инстанцируется std::unique_lock, то тут используется именно одна "слабая" концепция Mutex.


Только вот одного инстанцирования не достаточно.

НИ>А то, что такому описанию std::unique_lock можно сопоставить некое эквивалентное по смыслу описание, выраженное через две концепции с более конкретизированными предусловиями — это уже другой вопрос.


Так в чем здесь преимущества "слабой" концепции? Для спецификации методов std::unique_lock по прежнему используется switch по 'типам', а там где не используется — это простое наследование спецификаций.

Как только мы вводим 'шаблоны' спецификаций (а это и есть по сути 'слабая' концепция), наследование, и т.п. — автоматом получаем проблемы, аналогичные проблемам, возникающим при обычном использовании 'типов'. Лишние зависимости, хрупкие/толстые/etc. базовые интерфейсы, нарушения LSP, и т.д.

ЮЖ>>Где оно сформулировано?


НИ>30.4.1.1/3:

НИ>

The behavior of a program is undefined if:
НИ>[...]
НИ>— a thread that owns a mutex object calls lock() or try_lock() on that object

НИ>С точки зрения пользователя std::mutex нет никакой разницы между этим undefined behavior и undefined behavior, возникающим в результате несоблюдения условий, которые были бы явным образом специфицированы как предусловия.

17.6.3.11/1:
Violation of the preconditions specified in a function’s Required behavior: paragraph results in undefined
behavior unless the function’s Throws: paragraph specifies throwing an exception when the precondition is
violated.


Согласно этой формулировке — несоблюдение предусловий не всегда UB. В этом ракурсе очень интересно выглядит описание error conditions для mutex::lock. Когда я говорил о "завуалированных" предусловиях — я имел ввиду именно это.

НИ>Т.е. фактически отсутствие владения мьютексом со стороны текущего потока можно считать предусловием для вызова lock.


Хорошо — будем считать.

ЮЖ>>они там, кстати, нарушили свой любимый zero-overhead principle.


НИ>Где именно?


Здесь: "throwing an exception when the precondition is violated" — разрешается диагностировать ситуацию, при которой дальнейшее выполнение приводит к UB и возбуждать исключения. Там где это проиходит и нарушается zero-overhead principle, в частности во всех местах (где "precondition is violated") возбуждения стандартной библиотекой исключений, производных от std::logic_error.
Re[15]: api design: return code or exception - formal criter
От: Николай Ивченков  
Дата: 07.09.09 10:25
Оценка:
Юрий Жмеренецкий:

НИ>>А то, что такому описанию std::unique_lock можно сопоставить некое эквивалентное по смыслу описание, выраженное через две концепции с более конкретизированными предусловиями — это уже другой вопрос.


ЮЖ>Так в чем здесь преимущества "слабой" концепции?


Я не знаю, какие преимущества здесь видели авторы, но факт её применения, IMHO, налицо.

НИ>>С точки зрения пользователя std::mutex нет никакой разницы между этим undefined behavior и undefined behavior, возникающим в результате несоблюдения условий, которые были бы явным образом специфицированы как предусловия.


ЮЖ>

17.6.3.11/1:
ЮЖ>Violation of the preconditions specified in a function’s Required behavior: paragraph results in undefined
ЮЖ>behavior unless the function’s Throws: paragraph specifies throwing an exception when the precondition is
ЮЖ>violated.

ЮЖ>Согласно этой формулировке — несоблюдение предусловий не всегда UB.

Я и не говорил, что несоблюдение предусловий всегда влечёт undefined behavior. Достаточно и того, что иногда undefined behavior приводится как следствие несоблюдения предусловий. Если существуют критерии невозникновения undefined behavior, то с практической точки зрения не имеет никакого значения, обозначает ли документация эти критерии в качестве некоторых предусловий явным образом.

ЮЖ>В этом ракурсе очень интересно выглядит описание error conditions для mutex::lock. Когда я говорил о "завуалированных" предусловиях — я имел ввиду именно это.


Я вообще затрудняюсь сказать, в чём заключается суть "resource_deadlock_would_occur — if the current thread already owns the mutex and is able to detect it" и когда это может быть актуально.

НИ>>Т.е. фактически отсутствие владения мьютексом со стороны текущего потока можно считать предусловием для вызова lock.


ЮЖ>Хорошо — будем считать.


Если считать Lockable (в Boost) завершённой концепцией, то std::mutex и boost::mutex не соответствуют этой концепции, т.к. std::mutex и boost::mutex предъявляют более жёсткие предусловия.

ЮЖ>>>они там, кстати, нарушили свой любимый zero-overhead principle.


НИ>>Где именно?


ЮЖ>Здесь: "throwing an exception when the precondition is violated" — разрешается диагностировать ситуацию, при которой дальнейшее выполнение приводит к UB и возбуждать исключения. Там где это происходит и нарушается zero-overhead principle, в частности во всех местах (где "precondition is violated") возбуждения стандартной библиотекой исключений, производных от std::logic_error.


basic_string(const basic_string<charT,traits,Allocator>& str,
             size_type pos, size_type n = npos,
             const Allocator& a = Allocator());


Requires: pos <= str.size()
Throws: out_of_range if pos > str.size().

Где тут overhead? IMHO, тут проверка предусловия занимает очень незначительную часть времени от общих затрат на конструирование, так что её трудно назвать overhead-ом. Использование механизма исключений всё равно необходимо, т.к. у аллокатора нет иного способа сообщения об ошибке выделения памяти.
Re[3]: api design: return code or exception - formal criteri
От: Vain Россия google.ru
Дата: 07.09.09 10:37
Оценка: :)
Здравствуйте, minorlogic, Вы писали:

V>> После появились программисты библиотеки, которые поняли, что каждый раз включать галку в студии останавливаться на исключении в отладчике не катит и вставили ассерт перед самим throw.

M>Объясните подробнее пожалуйста этот кусок.
Чтобы не перезапускать приложение, которое уже грохнулось на исключении, ставят ассерт перед исключением чтобы вовремя отстановиться в отладчике, обычная практика.
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[5]: api design: return code or exception - formal criteri
От: Vain Россия google.ru
Дата: 07.09.09 10:46
Оценка: -1
Здравствуйте, Erop, Вы писали:

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

E>А что это даст, кроме дальнейшего снижения удобства использования библиотеки?
E>IMHO, качественный клинтский код -- это забота его авторов. Библиотека должна позволять писать качественный, и не должна мешать это делать или провоцировать на некачественный. Но бороться?
Одна библиотека не сможет этого обеспечить, нужны ещё нормальные программисты, которые её будут правильно использовать. А на практике, обычно, это не выполняется. Поэтому, иногда, лучше не использовать исключения, которые приводят к болоту, а использовать только коды возврата. При этом пользователь не сможет написать рабочий код без проверки кода возврата, что есть защита от дурака.
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[16]: api design: return code or exception - formal criter
От: Юрий Жмеренецкий ICQ 380412032
Дата: 07.09.09 11:30
Оценка:
Здравствуйте, Николай Ивченков, Вы писали:

ЮЖ>>>>они там, кстати, нарушили свой любимый zero-overhead principle.


НИ>>>Где именно?


ЮЖ>>Здесь: "throwing an exception when the precondition is violated" — разрешается диагностировать ситуацию, при которой дальнейшее выполнение приводит к UB и возбуждать исключения. Там где это происходит и нарушается zero-overhead principle, в частности во всех местах (где "precondition is violated") возбуждения стандартной библиотекой исключений, производных от std::logic_error.


НИ>

basic_string(const basic_string<charT,traits,Allocator>& str,
НИ>             size_type pos, size_type n = npos,
НИ>             const Allocator& a = Allocator());


НИ>Requires: pos <= str.size()
НИ>Throws: out_of_range if pos > str.size().

НИ>Где тут overhead? IMHO, тут проверка предусловия занимает очень незначительную часть времени от общих затрат на конструирование, так что её трудно назвать overhead-ом.

Смысл принципа: не хочу — не плачу. Если у меня из контекста использования автоматически вытекает выполнения предусловия — зачем мне нужна проверка "внутри"? На всякий случай? Нарушение в том, что в этом случае у меня нет рычага для ее отключения. А насколько это бьет по производительности — совершенно неважно.

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


Ты хочешь сказать что аллокатор кидает out_of_range? Это неверно. Он кидает bad_alloc — и к этому у меня претензий нет. А вот out_of_range к аллокатору не имеет никакого отношения.
Re[2]: api design: return code or exception - formal criteri
От: byleas  
Дата: 07.09.09 12:17
Оценка:
Здравствуйте, jazzer, Вы писали:

J>все функции в двух экземплярах, одни бросают, другие (у которых есть параметр boost::system::error_code & ec) — не бросают.

Проще объединить, что и предложили в N2838:
int func(int param, std::error_code& ec = throws())
{
  if(param == invalid_param_value){
    if(&ec == &throws())
      throw std::invalid_argument("param");
     else
            return EINVAL;
        }
    }
    // ... do the work
}

static const std::error_code* const _g_ec_throws = nullptr;

inline std::error_code& throws() { return *_g_ec_throws; }
Re[3]: api design: return code or exception - formal criteri
От: jazzer Россия Skype: enerjazzer
Дата: 07.09.09 12:29
Оценка:
Здравствуйте, byleas, Вы писали:

B>Здравствуйте, jazzer, Вы писали:


J>>все функции в двух экземплярах, одни бросают, другие (у которых есть параметр boost::system::error_code & ec) — не бросают.

B>Проще объединить, что и предложили в N2838:

Мы уже с Quasi это обсуждали, я по второму разу не буду
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.