2010-10-27 9 views
33

Giocando con this answer da user GMan I artigianale il seguente frammento (compilato con Visual C++ 9):Perché "operator void" non è invocato con la sintassi cast?

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

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

dopo scavalcando con il debugger ho scoperto che la fusione a void non invoca Class::operator void(), solo la terza invocare (invocando esplicitamente l'operatore) invoca effettivamente l'operatore, i due calchi non fanno nulla.

Perché il operator void non viene invocato con la sintassi del cast?

+4

Mi piace come fai sempre domande strane ma interessanti;) Ecco il mio +1. – ereOn

+0

Quale codice ti aspetti di eseguire * senza * il cast? In realtà nessuno ... perché il cast dovrebbe cambiarlo? – Eiko

+2

@Eiko: Se questo era 'operator int()' e ho scritto '(int) object;' quindi sarebbe stato chiamato 'operator int()'. Risulta che questo non è il caso di 'operator void()', quindi ho posto questa domanda. – sharptooth

risposta

26

La ragione tecnica si trova in §12.3.2:

Una funzione di conversione viene mai utilizzato per convertire un oggetto (possibilmente cv qualificato) per lo stesso tipo di oggetto (possibilmente cv qualificato) (o un riferimento ad esso), ad una classe di base (eventualmente qualificata per il cv) di quel tipo (o ad un riferimento ad esso), oppure a (eventualmente qualificato cv) void.

La logica è (probabilmente) per consentire §5.2.9/4 al lavoro:

Qualsiasi espressione può essere esplicitamente convertito in digitare il valore dell'espressione viene scartato “cv vuoto.”.

(void)expr supporre di non fare nulla per il valore risultante di qualsiasi espressione, ma se si chiama il vostro operatore di conversione non sarebbe scartare nulla. Quindi vietano l'uso di operator void nelle conversioni.


perché non farlo diventare mal formato per avere la conversione di tipo-id essere void? Chi lo sa, ma tenete a mente che non è del tutto inutile:

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) 

E 'ancora tecnicamente potenzialmente utile per qualcosa, quindi forse è razionale non abbastanza per renderlo mal formata.

+4

* "Perché non farlo apparire in modo errato che l'id del tipo di conversione sia" void'? " * Forse perché quel 'void' potrebbe essere nascosto dietro un typedef o un parametro template? – dyp

Problemi correlati