2010-10-27 7 views
33

Mientras jugaba con this answer por user GMan Construí el siguiente fragmento (compilado con Visual C++ 9):¿Por qué no se invoca el "operador void" con la sintaxis de conversión?

class Class { 
public: 
    operator void() {} 
}; 

Class object; 
static_cast<void>(object); 
(void)object; 
object.operator void(); 

después de pasar por encima con el depurador descubrí que la fundición hasta void no invoca Class::operator void(), sólo la tercera La invocación (con la invocación explícita del operador) en realidad invoca al operador, los dos moldes simplemente no hacen nada.

¿Por qué no se invoca el operator void con la sintaxis de conversión?

+4

Me encanta cómo siempre preguntas extrañas pero interesantes;) Aquí está mi +1. – ereOn

+0

¿Qué código esperarías que fuera ejecutado * sin * el molde? En realidad, ninguno ... ¿por qué debería el casting cambiar esto? – Eiko

+2

@Eiko: Si eso fuera 'operator int()' y yo escribimos '(int) object;' entonces se invocará 'operator int()'. Resulta que este no es el caso con 'operator void()', así que hice esta pregunta. – sharptooth

Respuesta

26

La razón técnica se encuentra en §12.3.2:

una función de conversión nunca se utiliza para convertir un objeto (posiblemente cv-cualificado) para el mismo tipo de objeto (posiblemente cv-cualificado) (o una referencia a él), a una clase base (posiblemente cv-calificada) de ese tipo (o una referencia a ella), o (posiblemente cv-calificado) nulo.

La razón es (probable) para permitir §5.2.9/4 al trabajo:

Cualquier expresión puede ser explícitamente convertir al tipo se descarta el valor de expresión “vacío cv.”.

(void)expr a supongo que hacer nada para el valor resultante de cualquier expresión, pero si se llama el operador de conversión no sería descartar nada. Por lo tanto, prohíben el uso de operator void en las conversiones.


por qué no hacer a mal formada para tener la conversión de tipo-id sea void? Quién sabe, pero tenga en cuenta que no es totalmente inútil:

struct foo 
{ 
    operator void() 
    { 
     std::cout << "huh?" << std::endl; 
    } 

}; 

typedef void (foo::*void_function)(); 

foo f; 
void_function func = &foo::operator void; 

(f.*func)(); // prints "huh" 
f.operator void(); // also does (which you knew) 

Todavía es técnicamente potencialmente útil para algo, así que tal vez eso es justificación suficiente para no hacerlo mal formada.

+4

* "¿Por qué no hacerlo mal formado para que la conversión-tipo-id sea' void'? " * Tal vez porque ese 'void' podría estar oculto detrás de un typedef o parámetro de plantilla? – dyp

Cuestiones relacionadas