Comments 11
От себя добавлю, что error_category::message не обязывает возвращать константную строку. Возможны прокси-категории, скажем, для группировки ошибок по типам, локализации, преобразования кодировок (привет Microsoft), конструирование сообщений на лету и многое другое.
Недавно Andrzej Krzemieński опубликовал пару статей про создание собственных error_code
и error_condition
:
Your own error code
Your own error condition
На мой взгляд, там более понятно объясняется разница между ними.
Увы, у технологии есть и минусы:
При сравнении
error_code
иerror_condition
делается минимум один виртуальный вызов, если они эквивалентны, и минимум два, если нет. Это дорого.
- В libstd++ (стандартная библиотека C++ на debian) между версиями 3.4.18 и 3.4.21 есть проблемы с совместимостью. Если такие два теста собрать на Ubuntu Trusty, а запустить на Ubuntu Xenial, первый выдаст неверный результат, а второй упадёт.
С такими минусами, в частности, столкнулись в LLVM и обходят их так:
https://github.com/llvm-mirror/llvm/commit/803fe1968007aa7a9c4f9674af648c9840f02a11
https://github.com/llvm-mirror/llvm/blob/master/include/llvm/Support/Errc.h
А вот накладку в реализации стандартной библиотеке сложно относить к минусам именно самой технологии. Кстати, спасибо что поделились этой информацией, не находил упоминаний об этом ранее.
Ситуаций, где мне потребовалось бы явно работать с платформозависимыми кодами вне платформенных обёрток, я стараюсь не допускать. Остаётся платформозависимое описание ошибки, которое нужно протащить через платформонезависимый код. Вот для него виртуальный вызов вполне адекватен, но и без него можно было бы просто протащить необрабатываемый char* (правда, его пришлось бы вычислять нелениво).
А сейчас я плачу в каждом сравнении, чтобы иметь возможность расширять категории ошибок в runtime, что мне за всю мою практику не понадобилось ни разу.
В одной из своих статьей Страуструп писал:
> In general, C++ implementations obey the zero-overhead principle: What you don’t use, you don’t pay for. And further: What you do use, you couldn’t hand code any better.
Для разработчиков LLVM и для меня это место так не выглядит. Но интересно было бы увидеть примеры активного расширения system_error в настоящих проектах (boost предлагать не надо).
Думаю, всё сильно зависит от частоты вызовов.
Если ошибка ожидается нечасто (а если они логгируются - это прямо видно по логам), то смысла оптимизировать и экономить на виртуальных вызовах нет.
Скажем, "не удалось открыть файл" - если он там ожидается ВСЕГДА, и ошибка прямо относится к исключительным ситуациям (например, закончилось место на диске, или отвалилась сетевая шара) - трудно представить, когда в этой ситуации надо экономить такты. А если закончилась память - то там вообще "мы все падаем, аааа!"
В общем, всё зависит от того, что считать ошибками. Этот путь должен быть исключительно редким, тогда ничего экономить не нужно.
Поддержка системных ошибок в C++