Я думаю, что что-то вроде следующего будет хорошим обходным путем?
Члены Const обычно проблематичны. Они препятствуют назначению, и они предотвращают построение перемещения. Тем не менее, присваиваемость не всегда может быть необходима для типа исключения, и рассматриваемый класс является быстрым и не исключает копирования в любом случае.
Таким образом, недостатки в этом случае могут быть не столь значительными, но не являются преимуществами,У вашего класса уже есть предварительное условие в конструкторе для нулевого завершения, и доступ к функциям-членам (и друзьям) инкапсулирован в A
.
Более фундаментально, однако, ваш класс исключений оченьсклонен к неправильному использованию. Рассмотрим следующие типичные сценарии:
throw A(some_local_string.c_str());
char local_buffer[N];
// fill local_buffer with formatted message
throw A(local_buffer);
Это приводит к неопределенному поведению.
Почему это более склонно к неправильному использованию, чем, например,. std :: string_view
Фактически использование std::string_view
делает ваш класс исключений склонным к неправильному использованию. Хранение const char*
будет иметь ту же проблему.
std::string_view
(и const char*
) хорошо подходит для аргументов функции, например, когда функция не хранит представление дольше, чем вызывающая сторонафункция существует. Но исключения в значительной степени используются исключительно для того, чтобы они жили дольше, чем их вызывающие, потому что они в основном всегда выбрасываются, что раскручивает вызывающего. просто используйте это в конструкторе вместо const char *, чтобы также показать намерение.
Принятие c_string_view
на самом деле не решает проблему, поскольку само по себе не подразумевает, что она будет сохраненабольше, чем const char*
. Лучшее, что вы можете сделать, это документировать, как можно использовать класс, что несколько неудовлетворительно, когда эти применения исключают общие шаблоны использования исключений.
Может быть, если вы назовете класс static_string_exception
или подобный, чтобы сделать ограничения болееочевидно.
от комментаторов:
Я бы просто взял магазин std :: string ...
.. вам лучше использоватьgood 'ol std :: string
std::string
тоже не идеальное решение. Это предотвратит отказ конструктора / назначения копирования (не строго, но другой альтернативой является завершение программы), что не подходит для типа исключения. Например, стандартные типы исключений не могут иметь конструктор / присваивание для копирования.
Как только вы достигнете маршрута копирования, вы также можете использовать std::runtime_error
, который сделает это за вас.