Подтвердить что ты не робот

Должен `unique_ptr <T const []>` принимать аргумент конструктора `T *`?

код:

#include <memory>
using namespace std;

struct T {};

T* foo() { return new T; }
T const* bar() { return foo(); }

int main()
{
    unique_ptr< T const >       p1( bar() );        // OK
    unique_ptr< T const [] >    a1( bar() );        // OK

    unique_ptr< T const >       p2( foo() );        // OK
    unique_ptr< T const [] >    a2( foo() );        // ? this is line #15
}

Примеры ошибок с Visual С++ 10.0 и MinGW g++ 4.4.1:

[d:\dev\test]
> cl foo.cpp
foo.cpp
foo.cpp(15) : error C2248: 'std::unique_ptr<_Ty>::unique_ptr' : cannot access private member declared in class 'std::unique_ptr<_Ty>'
        with
        [
            _Ty=const T []
        ]
        C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\INCLUDE\memory(2509) : see declaration of 'std::unique_ptr<_Ty>::unique_ptr'
        with
        [
            _Ty=const T []
        ]

[d:\dev\test]
> g++ foo.cpp -std=c++0x
c:\program files (x86)\codeblocks\mingw\bin\../lib/gcc/mingw32/4.4.1/include/c++/bits/unique_ptr.h: In function 'int main()':
c:\program files (x86)\codeblocks\mingw\bin\../lib/gcc/mingw32/4.4.1/include/c++/bits/unique_ptr.h:379: error: deleted function 'std::unique_ptr<_Tp [], _Tp_Deleter>::unique_ptr(_Up*, typename std::enable_if<std::is_convertible::value, void>::type*) [with _Up = T, _Tp = const T, _Tp_Deleter = std::default_delete<const T []>]'
foo.cpp:15: error: used here

[d:\dev\test]
> _

Мне кажется, что версия массива должна принимать одно и то же неявное const-добавление как версию без массива.

Разница в том, что версия массива не должна принимать указатель на производный класс и что механизм, который, по-видимому, пинается выше.

Является ли код действительным?

Если код формально недействителен, стандартная формулировка отражает намерение (т.е. соответствует DR)?

Если нет для первого и да ко второму, является ли намерение дефектным (т.е. снова является подходящим DR)?

4b9b3361

Ответ 1

Отчет о дефектах может быть уместным. В §20.7.1.3.1 говорится:

explicit unique_ptr(pointer p) noexcept;
unique_ptr(pointer p, see below d) noexcept;
unique_ptr(pointer p, see below d) noexcept;

Эти конструкторы ведут себя так же, как в основном шаблоне, за исключением того, что они не принимают типы указателей, которые конвертируются в указатель. [Примечание. Один метод реализации заключается в создании частных шаблонных перегрузок этих членов. - конечная нота]

Идея состоит в том, чтобы предотвратить преобразование производных к базовым, которые не работают с массивами. Но это неспецифично, и преобразование cv-квалификации также запрещено. Возможно, это нужно изменить, чтобы запретить конверсии указателей (§4.10), а не все преобразования указателей.