unique_ptr конструктор требует, чтобы Deleter не был - PullRequest
2 голосов
/ 05 мая 2020

unique_ptr (constructor) @ cppreference

unique_ptr( pointer p, /* see below */ d1 ) noexcept;
(3) 
unique_ptr( pointer p, /* see below */ d2 ) noexcept;
(4)

Вот 2 конструктора и описание для случая, когда Deleter не является справочным

a) If D is non-reference type A, then the signatures are:
unique_ptr(pointer p, const A& d) noexcept;
(1) (requires that Deleter is nothrow-CopyConstructible)
unique_ptr(pointer p, A&& d) noexcept;
(2) (requires that Deleter is nothrow-MoveConstructible)

Я проверил код g cc и llvm, но я не вижу, что требование nothrow выполняется. Конструкторы 3-4 помечены как noexcept, поэтому имеет смысл, что Deleter не должен бросать при вызове его конструкторов. Но я не уверен, почему в приведенном ими примере конструкторы не помечены как noexcept.

struct D { // deleter
    D() {};
    D(const D&) { std::cout << "D copy ctor\n"; }
    D(D&) { std::cout << "D non-const copy ctor\n";}
    D(D&&) { std::cout << "D move ctor \n"; }
    void operator()(Foo* p) const {
        std::cout << "D is deleting a Foo\n";
        delete p;
    };
};

1 Ответ

8 голосов
/ 05 мая 2020

Я проверил код g cc и llvm, но не вижу, что требование nothrow выполняется.

Оно не применяется - напрямую.
Вот фактические слова из стандарта :

Для первого конструктора, если D не является ссылочным типом, D должен соответствовать требованиям Cpp17CopyConstructible, и такая конструкция не должна выйти через исключение. Для второго конструктора, если D не является ссылочным типом, D должен соответствовать требованиям Cpp17MoveConstructible, и такая конструкция не должна завершаться через исключение.

Это означает, что if ваш конструктор копирования / перемещения завершается через исключение, у вас неопределенное поведение. [«должен» в этом случае является требованием к пользователю. ]

Если повезет, программа позвонит terminate с красивым сообщением. Однако у вас нет никаких гарантий.

(Позже) Примечание. Требуется НЕ то, чтобы они были noexcept, а чтобы они не выходили через исключение. Вот почему примеры на cppreference подходят.

...