2010-02-24 10 views
6

¿Cuál sería la forma más elegante también fijar el siguiente código:Proporcionar menos de operador para un elemento de un par

#include <vector> 
#include <map> 
#include <set> 
using namespace std; 

typedef map< int, int > row_t; 
typedef vector<row_t> board_t; 
typedef row_t::iterator area_t; 

bool operator< (area_t const& a, area_t const& b) { 
    return(a->first < b->first); 
}; 

int main(int argc, char* argv[]) 
{ 
    int row_num; 
    area_t it; 

    set< pair< int, area_t > > queue; 
    queue.insert(make_pair(row_num, it)); // does not compile 
}; 

Una forma de solucionarlo se está moviendo la definición de menos < a namespace std (lo sé,     que no se supone que hacerlo.)

namespace std { 
    bool operator< (area_t const& a, area_t const& b) { 
     return(a->first < b->first); 
    }; 
}; 

Otra solución obvia es la definición de menos de < para par < int, area_t> pero me gustaría evitar eso y ser capaz de definir el operador solo para el elemento del par donde no está definido.

+4

Ese es un nombre interesante que tiene para su conjunto allí;) –

+0

¿Qué hay en un nombre? Una rosa con cualquier otro nombre huela tan dulce. –

Respuesta

6

Cuando está implementando un comparador que implementa un enfoque de comparación específico y/o bastante exótico, es mejor usar una función nombrada o un objeto de función en lugar de secuestrar el operator < para tal fin. Diría que la forma natural de comparar un objeto std::pair sería usar una comparación lexicográfica. Como su comparación no es lexicográfica, tomar el control operator < podría no ser una buena idea. Mejor implementar una clase comparador

typedef pair< int, area_t > Pair; // give it a more meaningful name 

struct CompareFirstThroughSecond { 
    bool operator()(const Pair& p1, const Pair& p2) const { 
    if (p1.first != p2.first) return p1.first < p2.first; 
    return p1.second->first < p2.second->first; 
    } 
}; 

y utilizarlo con su contenedor

std::set< Pair, CompareFirstThroughSecond > queue; 

(espero Descifré su intención desde el código original correctamente).

También puede implementar el método anterior operator() como un método de la plantilla, por lo que es utilizable con todos los tipos basados ​​en std::pair con un iterador como miembro second. Sin embargo, puede que no tenga sentido, ya que su comparación es lo suficientemente "exótica".

+1

Parece que le falta que 'std :: pair' ya implemente' operator '', y OP se pregunta cómo conectar un comparador para el segundo miembro (iterador). – UncleBens

+0

@UncleBens: Oh, lo tengo. Tienes razón. Aún así, lo que propuse debería funcionar. Además, tratar de implementar un comparador para el tipo de iterador a través de la sobrecarga del operador es una tarea arriesgada, ya que en el caso general el iterador puede ser implementado por un tipo incorporado (para el cual la sobrecarga del operador no es posible). – AnT

+1

@UncleBens: es una forma excelente de expresarlo. Quiero _plug-in_ un operador para el segundo elemento del par. @AndreyT - Necesitaría comparar las entradas del par primero y, si son iguales, continuar y comparar los miembros 'area_t' del par. Eso funcionaria. Pero esa es precisamente la solución que estaba tratando de evitar: 'operator <' ya está implementado para 'std :: pair' y para ints. No quiero reinventar la rueda. (Además, eso es una gran cantidad de tipeo). –

Cuestiones relacionadas