ideas icon indicating copy to clipboard operation
ideas copied to clipboard

Добавить в std::runtime_error и std::logic_error (и их наследников) конструктор, который получает std::string_view

Open eao197 opened this issue 3 years ago • 6 comments

Судя по документации на cppreference и по драфту стандарта (раздел 19.2) у std::runtime_error и std::logic_error есть конструкторы, которые получают const std::string& и const char * (при этом подразумевается, что const char* -- это строка с 0-символом в конце). Но нет конструктора, который бы получал std::string_view.

После добавления в стандарт std::string_view выглядит странно, что стандартные классы исключений не могут получать описание ошибки в виде std::string_view.

Отсутствие такого конструктора создает неудобства, например, в таких случаях:

// Throws an exception if operation can't be started.
void ensure_valid_state_for_operation(std::string_view operation_description) {
  if(!check_first_condition()) throw std::runtime_error{operation_description};
  if(!check_second_condition()) throw std::runtime_error{operation_description};
  ...
}

Такой код не скомпилируется. Нужно будет делать преобразование из string_view в string, но при этом мы можем получить две аллокации: первая при создании временного string, вторая -- при создании еще одной копии внутри runtime/logic_error (т.к. string принимается по константной ссылке и содержимое временного string-а не может быть перемещено внутрь runtime/logic_error).

eao197 avatar Feb 09 '22 09:02 eao197

выглядит странно, что стандартные классы исключений не могут получать описание ошибки в виде std::string_view.

Да, но обычно описание ошибки генерируют в рантайме, чтобы иметь в нём информацию для отладки; тут как раз подходит ссылка на std::string.

pavelkryukov avatar Feb 09 '22 22:02 pavelkryukov

Да, но обычно описание ошибки генерируют в рантайме,

Это далеко не всегда так. Бывают случаи когда проверяются аргументы функции/метода:

void do_something(const some_type * target, int retries) {
  if(!target) throw_invalid_parameter_exception("target can't be null");
  if(retries < -10 || retries > 15) throw_invalid_parameter_exception("retries is out of allowed range [-10, 15]");
  ...
} 

Раз уж в C++ добавили std::string_view, то было бы хорошо иметь возможность отказаться от использования const char * в том числе и при выбрасывании runtime/logic_error.

чтобы иметь в нём информацию для отладки; тут как раз подходит ссылка на std::string.

Даже когда описание исключения генерируется автоматически, то далеко не всегда это происходит через std::string. Описание может быть помещено внутрь какого-то std::array<char, 256> на стеке. И при формировании описания необязательно будет использоваться sprintf, который добавляет 0-символ в конце. Так что в этом std::array может тупо не быть 0-символа, необходимого для передачи описания в runtime/logic_error в виде const char*.

eao197 avatar Feb 10 '22 05:02 eao197

в #263 есть ссылка на предложение P0506

pavelkryukov avatar Feb 10 '22 23:02 pavelkryukov

в https://github.com/cpp-ru/ideas/issues/263 есть ссылка на предложение 0506

Я так понимаю, что судьба этого предложения печальна. Раз с 2017-го года никаких подвижек нет.

eao197 avatar Feb 11 '22 06:02 eao197

Я так понимаю, что судьба этого предложения печальна. Раз с 2017-го года никаких подвижек нет.

P0506 более агрессивное:

  • не добавлять новых конструкторов, а заменить старые (const char*/const std::string&)
  • потрогать std::regex, std::filesystem и т. д.

pavelkryukov avatar Feb 12 '22 10:02 pavelkryukov

По факту стандартные исключения не могут получать std::string_view, хотя это было бы полезно. И логично, раз уж в C++17 добавили этот самый std::string_view.

eao197 avatar Feb 12 '22 11:02 eao197