2012-02-28 10 views
6

No entiendo por qué las siguientes obras (aunque estoy feliz de que funciona!):¿Por qué funciona esto? std :: set encontrar con clave de búsqueda y comparador de encargo

que pueden definir una std::set de objetos con un comparador personalizado. Este comparador personalizado funciona al comparar algunas variables miembro de los dos Objetos que se comparan. PERO entonces puedo usar la función set.find(x) siendo x del tipo de variable miembro en lugar de un objeto en sí, ¡y funciona!

Aquí es un ejemplo extremadamente simplificado:

my_class.h

class my_class //just hold an integer 
{ 
    public: 
     int an_int; 

    my_class(int new_int) : an_int(new_int) 
    { } 


    //compare instances of this class by comparing their integers... 
    struct compare_instances 
    {  
     bool operator() (const my_class &a, const my_class &b) const 
     { 
     return a.an_int < b.an_int; 
     } 
    }; 
}; 

main.cpp:

... 
std::set<my_class, my_class::compare_instances> my_class_set; 
my_class_set.insert(my_class(18)); 
my_class_set.insert(my_class(7) ); 
my_class_set.insert(my_class(22)); 

std::set<my_class, my_class::compare_instances>::const_iterator found_it 
        = my_class_set.find(18); 
std::fprintf(stderr, "found_it->an_int = %d\n", found_it->an_int); 

salida: "found_it-> an_int = 18" !!!! !!

Hubiera esperado que el código anterior no se compilara y que el compilador me gritara que "18 no es del tipo my_class". Pero no ...

¿Los argumentos a .find no deberían ser del mismo tipo que los elementos del set? Eso es lo que la documentación parece decir ...

+0

mira a tu constructor: 'my_class (int new_int)'. puedes crear un 'my_class' a partir de un' int'. intente y 'find (" blah ")' y no compilará :) – vulkanino

Respuesta

12

Esto funciona porque int es implícitamente convertible a su clase. Cualquier constructor que no esté marcado explicit y pueda invocarse con exactamente un argumento que no sea del tipo de la clase define una conversión implícita. Efectivamente, esto significa que, siempre que se espere un objeto de tipo de clase, también puede usar un int, y se convertirá automáticamente.

+0

Ok, ha agregado todos mis puntos a su respuesta. Eliminaré mis otros comentarios. 8v) –

+0

@FredLarson, aunque tal vez no esté relacionado, ¿recomendaría ** siempre ** declarar explícitamente a los constructores? – vulkanino

+0

@vulkanino: si no quiere una conversión implícita, puede que no sea una mala idea. No estoy al tanto de ningún problema con agregar 'explicit' a un constructor, incluso si no se puede utilizar para la conversión implícita. –

Cuestiones relacionadas