Почему std::unique_ptr явно не требует удаления без исключений?

В документации сказано, что Deleter должен быть:

  • не строить
  • nothrow callable (потому что он вызывается из ~unique_ptr() noexcept
  • неразрушаемый (по указанной выше причине)

Мой вопрос в том, почему uniqut_ptr определено, чтобы разрешить Deleter, который может бросить. Например. следующие Deleter разрешены всеми конструкторами unique_ptr:

struct BadDeleter
{
    BadDeleter() noexcept(false) {}
    ~BadDeleter() noexcept(false) {}
    BadDeleter(const BadDeleter&) noexcept(false) {}
    BadDeleter(BadDeleter&) noexcept(false) {}
    BadDeleter(BadDeleter&&) noexcept(false) {}
    void operator()(char* p) const noexcept(false) {
        delete p;
    };
};

Текущая демонстрация


person Kentzo    schedule 06.03.2018    source источник
comment
Где именно это говорит то, что вы утверждаете в первом предложении?   -  person Kerrek SB    schedule 07.03.2018
comment
В какой документации это указано?   -  person NathanOliver    schedule 07.03.2018
comment
Конструкторы noexcept, сброс noexcept и деструктор определен без noexcept(false). Я не понимаю, как под этими определениями может кидать Deleter.   -  person Kentzo    schedule 07.03.2018
comment
Если выбрасывает, то это УБ. noexcept не является частью сигнатуры функции, поэтому вы не можете проверить, помечен ли удаляющий объект или нет.   -  person NathanOliver    schedule 07.03.2018
comment
noexcept является частью сигнатуры функции, по крайней мере, в C++14.   -  person Kentzo    schedule 07.03.2018
comment
Ах, С++17. Я забыл, что они добавили это. Они могут измениться unique_ptr в будущем стандарте. Когда это было впервые сделано, хотя вы не могли бы сказать.   -  person NathanOliver    schedule 07.03.2018
comment
На самом деле я больше не уверен в своем предыдущем заявлении: я пробовал тот же фрагмент кода с GCC, и он компилируется . Сбой только с MSVS 2015 Update 3. Тем не менее, начиная с C++ 11, существуют служебные функции для проверки наличия исключения. Я ожидаю, что они будут использоваться.   -  person Kentzo    schedule 07.03.2018


Ответы (1)


Стандарт определяет только требования к удалению uniqe_ptr на основе операций unique_ptr. Хотя в этих требованиях всегда говорится что-то вроде

~unique_ptr();
Требования: Выражение get_deleter()(get()) должно быть правильно сформировано, должно иметь четко определенное поведение и не должно вызывать исключений.

стандарт никогда явно не указывает, что средство удаления должно иметь noexcept operator().

Я предполагаю, что эта формулировка была выбрана, чтобы сохранить обратную совместимость с C++14. В этом стандарте noexcept не было частью сигнатуры функции, и добавление этого требования в C++17, вероятно, сломало бы большую часть кода, где использовались пользовательские удаления без явной маркировки их операций как noexcept.

person Miles Budnek    schedule 06.03.2018
comment
Я надеюсь, что когда выйдут компиляторы, они хотя бы предупредят об отсутствии noexcept. - person Kentzo; 07.03.2018