2011-07-22 13 views
10

Considere el siguiente código.¿Por qué el compilador no realiza una conversión de tipo?

#include <iostream> 
#include <string> 

struct SimpleStruct 
{ 
    operator std::string() { return value; } 
    std::string value; 
}; 

int main() 
{ 
    std::string s; // An empty string. 
    SimpleStruct x; // x.value constructed as an empty string. 

    bool less = s < x; // Error here. 
    return 0; 
} 

Este código no se compila ni en g ++ ni en Microsoft Visual C++. El informe de error dado por los compiladores es no match for operator '<' in 's < x'. La pregunta es por qué el compilador no simplemente convierte el SimpleStruct x en string según el operator string() dado y luego usa operator < (string, string)?

Respuesta

13

operator< para std::string es una plantilla de función. Las sobrecargas son:

template<class charT, class traits, class Allocator> 
    bool operator< (const basic_string<charT,traits,Allocator>& lhs, 
      const basic_string<charT,traits,Allocator>& rhs); 
    template<class charT, class traits, class Allocator> 
    bool operator< (const basic_string<charT,traits,Allocator>& lhs, 
      const charT* rhs); 
    template<class charT, class traits, class Allocator> 
    bool operator< (const charT* lhs, 
      const basic_string<charT,traits,Allocator>& rhs); 

Su llamada no coincide con ninguna de las sobrecargas disponibles, por lo que todo lo que se eliminan de una lista de candidatos. Como no se eligió una plantilla de función como candidato para resolver la llamada, no hay nada para convertir SimpleStruct.

template <class T> 
class String 
{ 
}; 

template <class T> 
bool operator< (const String<T>&, const String<T>&) { return true; } 


//if a suitable non-template function is available, it can be picked 
//bool operator< (const String<char>&, const String<char>&) { return true; } 

struct SimpleStruct 
{ 
    operator String<char>() { return value; } 
    String<char> value; 
}; 

int main() 
{ 
    String<char> s; 
    SimpleStruct ss; 
    s < ss; //the call doesn't match the function template, leaving only the commented-out candidate 
} 
+1

+1, esta respuesta es correcta. 'string :: operator <()' no toma el argumento como 'const string &', pero 'basic_string <>'; si sobrecarga 'operator '' globalmente, entonces funciona. http://www.ideone.com/vMERa – iammilind

+1

Eh, 'std :: string' es solo un typedef para' std :: basic_string '. 'typedef' no introduce un nuevo tipo, y por lo tanto no afecta a la sobrecarga. – MSalters

+2

El problema subyacente es que la deducción de 'charT' en' plantilla bool operator <(std :: basic_string const & lhs, std :: basic_string const & rhs); 'falla. No hay' charT' para el cual 'basic_string ' _equals_ 'SimpleStruct'. Eso lo elimina del conjunto de sobrecarga. – MSalters

Cuestiones relacionadas