c++ visual-studio-2010 gcc c++11 unique-ptr

c++ - Debería permitirse std:: unique_ptr<void>



visual-studio-2010 gcc (4)

GCC en realidad tiene un código para evitarlo, pero no funcionó hasta hace poco.

El unique_ptr de GCC tiene una aserción estática en default_deleter::operator() que debería rechazar tipos incompletos:

static_assert(sizeof(_Tp)>0, "can''t delete pointer to incomplete type");

Sin embargo, como una extensión, GCC admite sizeof(void) , por lo que la aserción no falla, y porque aparece en un encabezado del sistema ni siquiera da una advertencia (a menos que use -Wsystem-headers ).

Descubrí este problema recientemente, así que para solucionarlo lo agregué hace 10 días :

static_assert(!is_void<_Tp>::value, "can''t delete pointer to incomplete type");

Por lo tanto, si utiliza el código más reciente en el enlace troncal, su ejemplo no se compila, tal como lo exige el estándar.

Esta es una pregunta muy simple. Considera el siguiente código:

#include <iostream> #include <memory> typedef std::unique_ptr<void> UniqueVoidPtr; int main() { UniqueVoidPtr p(new int); return 0; }

Compilando con cygwin (g ++ 4.5.3) con el siguiente comando g++ -std=c++0x -o prog file.cpp funciona bien. Sin embargo, compilando con el compilador de Microsoft (ya sea VS 2010 o 2013) me sale este error:

C:/Program Files (x86)/Microsoft Visual Studio 10.0/VC/INCLUDE/memory(2067) : error C2070: ''void'': illegal sizeof operand C:/Program Files (x86)/Microsoft Visual Studio 10.0/VC/INCLUDE/memory(2066) : while compiling class template member function ''void std::default_delete<_Ty>::operator ()(_Ty *) const'' with [ _Ty=void ] C:/Program Files (x86)/Microsoft Visual Studio 10.0/VC/INCLUDE/type_traits(650) : see reference to class template instantiation ''std::default_delete<_Ty>'' being compiled with [ _Ty=void ] C:/Program Files (x86)/Microsoft Visual Studio 10.0/VC/INCLUDE/memory(2193) : see reference to class template instantiation ''std::tr1::is_empty<_Ty>'' being compiled with [ _Ty=std::default_delete<void> ] foo1.cpp(7) : see reference to class template instantiation ''std::unique_ptr<_Ty>'' being compiled with [ _Ty=void ]

Es esto esperado? Estoy escribiendo una clase en la que quería tener un puntero único en la clase. Mientras trataba de descifrar la semántica de un constructor de movimiento para la clase, me topé con esto (supongo que porque finalmente obtuve mi constructor de movimiento codificado correctamente, es decir, los otros errores fueron corregidos).


La pregunta se reduce a:

void* p = new int; delete p;

En cuanto a n3797 5.3.5 Eliminar, creo que la delete p es un comportamiento indefinido debido a los tipos no coincidentes, por lo que el comportamiento del compilador es aceptable ya que el código tiene errores.

Nota: esto difiere de shared_ptr<void> , ya que usa borrado de tipo para hacer un seguimiento del tipo original de puntero pasado.


MSVC tiene razón, mientras que GCC está equivocado:

Estándar (3.9 / 5):

Los tipos de objetos incompletos y los tipos vacíos son tipos incompletos

Estándar (20.7.1.1.2 / 4):

Si T es un tipo incompleto, el programa está mal formado


No elimine las variables de void * .

Si desea trabajar con algo como Win32 Handles, proporcione un eliminador personalizado.

Por ejemplo:

void HandleDeleter(HANDLE h) { if (h) CloseHandle(h); } using UniHandle = unique_ptr<void, function<void(HANDLE)>>;

Entonces:

UniHandle ptr(..., HandleDeleter);