Должен ли `unique_ptr <T const []>` принимать аргумент конструктора `T *`? - PullRequest
13 голосов
/ 16 декабря 2011

Код:

#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 C ++ 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)?

1 Ответ

9 голосов
/ 16 декабря 2011

Отчет о дефекте может быть уместным. §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), а не все преобразования указателей.

...