искомый конец строки - PullRequest
       70

искомый конец строки

0 голосов
/ 18 октября 2019

Использование std::string_view в следующем сценарии:

struct A : public std::exception{
    A (const char* c) : v_(c){}
    const char* what() const noexcept override;

private:
    std::string_view v_;
};

Приведенная выше идея работает нормально, и теперь copy-ctor будет по умолчанию noexcept (что отлично подходит для типа исключения!) - истрока также «проверяется» на сайте вызова.

Однако остается только то, что семантически string_view не гарантируется нулевым завершением (хотя в этом случае мы написали код так, чтобы онбудет - было бы лучше, если бы это было гарантировано для этого конкретного случая, как если бы у него был только тот конструктор, который мы на самом деле использовали.

Я думаю, что что-то вроде следующего будет хорошим обходным путем?

struct c_string_view {
  c_string_view(const char* c) : sv_{c}{};
  const std::string_view sv_;
};

Но я хотел знать, есть ли у кого-то еще эта проблема (и что они сделали) или я пропускаю что-то симпел?

1 Ответ

3 голосов
/ 18 октября 2019

Я думаю, что что-то вроде следующего будет хорошим обходным путем?

Члены 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_viewconst char*) хорошо подходит для аргументов функции, например, когда функция не хранит представление дольше, чем вызывающая сторонафункция существует. Но исключения в значительной степени используются исключительно для того, чтобы они жили дольше, чем их вызывающие, потому что они в основном всегда выбрасываются, что раскручивает вызывающего. просто используйте это в конструкторе вместо const char *, чтобы также показать намерение.

Принятие c_string_view на самом деле не решает проблему, поскольку само по себе не подразумевает, что она будет сохраненабольше, чем const char*. Лучшее, что вы можете сделать, это документировать, как можно использовать класс, что несколько неудовлетворительно, когда эти применения исключают общие шаблоны использования исключений.

Может быть, если вы назовете класс static_string_exception или подобный, чтобы сделать ограничения болееочевидно.


от комментаторов:

Я бы просто взял магазин std :: string ...

.. вам лучше использоватьgood 'ol std :: string

std::string тоже не идеальное решение. Это предотвратит отказ конструктора / назначения копирования (не строго, но другой альтернативой является завершение программы), что не подходит для типа исключения. Например, стандартные типы исключений не могут иметь конструктор / присваивание для копирования.

Как только вы достигнете маршрута копирования, вы также можете использовать std::runtime_error, который сделает это за вас.

...