Para entender el enum
, comience considerando el destructor sin él:
~scoped_ptr() {
delete ptr_;
}
donde ptr_
esta a C*
. Si el tipo C
es incompleta en este punto, es decir, todo lo que el compilador sabe que es struct C;
, a continuación, (1) un defecto generado no hacer nada destructor se utiliza para la instancia C señaló. Es poco probable que eso sea lo correcto para un objeto administrado por un puntero inteligente.
Si la eliminación mediante un puntero a tipo incompleto siempre tuvo un comportamiento indefinido, entonces el estándar podría requerir que el compilador lo diagnostique y falle. Pero está bien definido cuando el destructor real es trivial: conocimiento que el programador puede tener, pero el compilador no. No entiendo por qué el lenguaje define y permite esto, pero C ++ admite muchas prácticas que hoy en día no se consideran mejores prácticas.
Un tipo completo tiene un tamaño conocido y, por lo tanto, sizeof(C)
se compilará si y solo si C
es un tipo completo, con un destructor conocido. Por lo que se puede utilizar como guardia. Una forma sería simplemente
(void) sizeof(C);
Me supongo que con un poco compilador y las opciones del compilador optimiza la basura antes de que pudiera notar que no debería compilar, y que el enum
es una manera de evitar este tipo de comportamiento no conforme compilador:
enum { type_must_be_complete = sizeof(C) };
Una explicación alternativa para la elección de enum
una expresión en lugar de simplemente descartada, es simplemente una preferencia personal.
O como sugiere James T. Hugget en un comentario a esta respuesta, "La enumeración puede ser una forma de crear un mensaje de error pseudoportátil en tiempo de compilación".
(1) El destructor de hacer nada generado por defecto para un tipo incompleto era un problema con el antiguo std::auto_ptr
. Fue tan insidioso que se abrió paso en un artículo de GOTW sobre el idioma PIMPL , escrito por el presidente del comité internacional de estandarización de C ++ Herb Sutter. Por supuesto, hoy en día eso std::auto_ptr
está desaprobado, en su lugar se utilizará algún otro mecanismo.
ptr_
en elsizeof
como ensizeof(*ptr_)
lugar desizeof(C)
.