Почему создание shared_ptr из unique_ptr массива больше не разрешено?

От cppreference:

В С++ 11 и С++ 14 можно построить a std::shared_ptr<T> из a std::unique_ptr<T[]>:

std::unique_ptr<int[]> arr(new int[1]);
std::shared_ptr<int> ptr(std::move(arr));

Так как shared_ptr получает свой дебит (a std::default_delete<T[]>) из unique_ptr, массив будет быть правильно освобожден.

Это больше не разрешено в С++ 17. Вместо формы массива std::shared_ptr<T[]>.

Почему это не разрешено в С++ 17? Что изменилось?

Ответ 1

p0497r0:

Неправильное ограничение для построения shared_ptr из unique_ptr

[...]

Основываясь на опыте внедрения, я считаю, что правильная форма:

Примечание. Этот конструктор не должен участвовать в разрешении перегрузки, если Y* не совместим с T* и unique_ptr<Y, D>::pointer может быть конвертирован в element_type*.

Проверка "совместим с" предотвращает нежелательные преобразования от unique_ptr<T[]> до shared_ptr<T>, а проверка "конвертируемый в" гарантирует, что результат unique_ptr<Y, D>::get() может быть сохранен в shared_ptr и возвращен shared_ptr<T>::get().

Другими словами, это было намеренно недопустимо только потому, что оно не должно быть действительным, а не просто побочным эффектом других изменений.

Это имеет смысл для меня. shared_ptr<T>, вероятно, будет читаться другими программистами, указывая только на один объект T. Требование программистов использовать shared_ptr<T[]>, когда они хотят несколько объектов T, приводит к более читаемому коду.

Примечание: эта правильная форма не входит в стандарт. Однако обоснование частично является комментарием того, что находится в стандарте.