2013-07-05 1 views
2

J'ai un comportement que je ne comprends pas. J'ai observé cela sur VS2005, mais IDEONE (using GCC 4.7.2) outputs fondamentalement la même chose.Pourquoi la conversion implicite ne fonctionne-t-elle pas avec un large ostream?

Voici le code:

#include <iostream> 
#include <string> 

struct UserString { 
    const char* p; 
     operator const char*() const { 
       std::cout << "! " << __FUNCTION__ << std::endl; 
       return p; 
     } 

     UserString() 
     : p ("UserString") 
     { } 
}; 

struct WUserString { 
     const wchar_t* p; 
     operator const wchar_t*() const { 
       std::cout << "! " << __FUNCTION__ << std::endl; 
       return p; 
     } 

     WUserString() 
     : p (L"WUserString") 
     { } 
}; 


int main() { 
     using namespace std; 
     cout << "String Literal" << endl; 
     cout << string("std::string") << endl; 
     cout << UserString() << endl; 
     cout << static_cast<const char*>(UserString()) << endl; 

     wcout << L"WString Literal" << endl; 
     wcout << wstring(L"std::wstring") << endl; 
     wcout << WUserString() << endl; 
     wcout << static_cast<const wchar_t*>(WUserString()) << endl; 

     return 0; 
} 

Voici la sortie:

String Literal 
std::string 
! operator const char* **** "works" 
UserString    **** 
! operator const char* 
UserString 
WString Literal 
std::wstring 
! operator const wchar_t* **** "doesn't" - op<<(void*) is used 
0x80491b0     **** 
! operator const wchar_t* 
WUserString 

Qu'est-ce qui se passe ici?!?

+0

Perte d'iostream standard. Il n'a pas besoin de votre convertisseur pour accepter une valeur de pointeur. Vous perdez parce que celui-ci est moins cher. –

+0

@HansPassant - Votre commentaire n'explique pas pourquoi le comportement est différent pour 'char' vs' wchar_t'. –

Répondre

3

Il y a une spécialisation partielle pour basic_ostream

template<class _TraitsT> 
basic_ostream<char, _TraitsT>& 
    operator<<(basic_ostream<char, _TraitsT>& _Stream, const char* _String); 

qui est un bon moyen pour l'cout << UserString() cas.

Il n'y a rien de semblable pour wchar_t et WUserString(), de sorte que le meilleur match sera fonction membre

basic_ostream& operator<<(const void* _Address); 

pour que (comme dans la plupart des cas « inhabituelles »).

+0

Merci. Ceci explique cela. Connaissez-vous ou avez-vous un pointeur pour savoir pourquoi cette spécialisation partielle existe pour 'char *'? L'asymétrie ici est un peu ennuyante. –

+0

"inhabituel" est un euphémisme sympa ;-) ... IMHO, 'operator << (const void * _Address);' est plus un bug qu'une fonctionnalité. Je pense que dans tous les cas où je l'ai utilisé, il y a 20 cas où ça m'a mordu à l'exécution. –

+1

Je suppose que c'est juste de l'histoire, mais je n'ai aucune preuve réelle. Il existe plusieurs autres spécialisations pour 'char' et' char * '(et même pour' signed char' et 'unsigned char') qui pourraient avoir été considérées comme des chances pour certaines optimisations, éventuellement. –

Questions connexes