2011-12-16 7 views
13

Código:¿Debería `unique_ptr <T const []>` aceptar un argumento de constructor `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 
} 

Ejemplo errores con Visual C++ 10.0 y 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] 
> _ 

Me parece que la versión matriz debe aceptar el mismo implícita const-añadiendo como la no -Variante.

La diferencia es que la versión de matriz no debe aceptar el puntero a una clase derivada, y esa es la maquinaria que aparentemente inicia más arriba.

¿Es válido el código?

Si el código es formalmente inválido, ¿la redacción de la norma refleja la intención (es decir, es una DR apropiada)?

Si no al primero y sí al segundo, ¿el intento es defectuoso (es decir, de nuevo, es un DR apropiado)?

Respuesta

9

Un informe de defectos puede ser apropiado. §20.7.1.3.1 dice,

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

Estos constructores se comportan de la misma que en la plantilla principal, excepto que no aceptan los tipos de puntero que son convertibles a puntero. [Nota: Una técnica de implementación es crear sobrecargas de plantillas privadas de estos miembros. - nota final]

La idea es claramente evitar las conversiones derivadas a la base que no funcionan con las matrices. Pero es inespecífico y la conversión de cv-calificación está prohibida también. Tal vez debería cambiarse para prohibir conversiones de puntero (§4.10), no todas las conversiones de punteros.

+1

"tipos de puntero que son convertibles en puntero" - y para ser realmente quisquilloso, ¿no es este lenguaje plano incorrecto de todos modos? 'puntero' es un tipo de puntero que es convertible en puntero (por ejemplo, al describir conceptos, si alguna función devuelve un tipo" convertible a T ", no significa que no debe ser T). Pero no creo que la intención fuera la de exceptuar 'puntero', así como punteros a los tipos derivados ;-) –

+0

publiqué una cantidad importante de recursos para csC++, pero puede llevar un tiempo aparecer ... así que solo para obtener información, También cité lo que creo que es la intención/razón en §20.7.1.3/1 2.º guión, "Los punteros a los tipos derivados de T son rechazados por los constructores, y al reiniciar" :-) –

+2

Esto me parece un defecto. Por favor, siga en: http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#submit_issue. Implementé una solución en libC++ (http://libcxx.llvm.org/). ¡Fue más difícil acertar de lo que estaba adivinando! –

Cuestiones relacionadas