2012-01-27 13 views
14

Ho un codice che compila bene in VS 10.0 ma dopo aver inserito alcuni elementi nella mappa Ordini di seguito ricevo un errore" operatore non valido < "nella libreria di debug di Microsoft. Il mio operatore in meno è semplice, confronta solo la stringa di 8 byte char per char. Qualcuno ha idea del perché riceverei questo errore?Errore STL in meno e errore "operatore non valido <

Grazie, Mike

typedef struct MY_orderID_t 
{ 
    char orderID[8]; 
} MY_orderID_t; 

struct std::less<MY_orderID_t> 
{ 
    bool operator()(const MY_orderID_t& k1, const MY_orderID_t& k2) const 
    { 
     for(int i=0; i < 8; i++) 
     { 
      if(k1.orderID[i] < k2.orderID[i]) 
      return(true); 
     } 
     return(false); 
    } 
}; 

std::map< MY_orderID_t, MY_order_t > Orders[5]; 

risposta

0

Oltre eventuali possibili errori che non vedo al momento, questo costrutto è no:

struct std::less<MY_orderID_t> 
{ /**/ } 

std::less è già un tipo, quindi non puoi ridefinirlo come un altro tipo.

+0

E [questo altro post] (http://stackoverflow.com/questions/2282349/specialization-of-templateclass-tp-struct-stdless-in- different-namespace) mostra il modo giusto per specializzare 'std :: less'. –

27

credo che il problema qui è che il metodo di confronto tra due MY_orderID_t s' non è un strict weak order, il tipo di ordinare relazione richiesta dal STL C++. Per essere un ordine rigoroso deboli, il vostro operatore minore deve avere le seguenti quattro proprietà:

  1. Irreflexivity: x < x è sempre false.
  2. Antisimmetria: Se x < y, quindi y < x è sempre falso.
  3. Transito: Se x < ye y < z, allora x < z è sempre true.
  4. Transitività dell'equivalenza: Se x e y sono incomparabili e y e z sono incomparabili, quindi x e z sono incomparabili.

In questo momento, l'ordine non obbedisce alle proprietà (2) o (3).

* In primo luogo, (2) viene violato dal seguente:

(0, 4) < (2, 2) 
(2, 2) < (0, 4) 

* In secondo luogo, (3) viene violata, perché

(0, 1) < (2, 0) < (-1, 1) 

// but 

(0, 1) < (-1, 1) // Fail 

Per risolvere questo problema, invece di utilizzare il confronto si attualmente hanno, invece usare un lexicographical comparison come questo:

return std::lexicographical_compare(k1.orderID.begin(), k1.orderID.end(), 
            k2.orderID.begin(), k2.orderID.end()); 

Questo confronto è un rigoroso ordine debole ed è quello che viene utilizzato da tutti i contenitori STL per impostazione predefinita. Passare a questo confronto obbedisce alle proprietà (1) - (4) e dovrebbe far sì che tutto funzioni correttamente.

Spero che questo aiuti!

+0

Per ulteriori dettagli, consultare questo eccellente articolo: [Order I Say!] (Http://cpp-next.com/archive/2010/02/order-i-say/). – ildjarn

3

@templatetypedef affronta i requisiti per un std::less specializzazione da utilizzare con map, da un punto puramente sintattico di vista:

  • È necessario #include<functional> e <map>

  • vi manca } tra char orderID[8]; e MY_orderID_t; nella riga successiva.

  • e:

    struct std::less<MY_orderID_t> 
    { 
        /* ... */ 
    }; 
    

    dovrebbe essere:

    namespace std { 
    template <> 
    struct less<MY_orderID_t> 
    { 
        /* ... */ 
    }; 
    } 
    
5

@templatetypedef dice che cosa c'è di sbagliato con la versione corrente.

Ecco una soluzione molto più leggibile:

struct MY_orderID_type 
{ 
    char orderID[8]; 
    bool operator<(const MY_orderID_type& other) const 
    { return memcmp(orderID, other.orderID, 8) < 0; } 
}; 

std::map< MY_orderID_type, MY_order_type > Orders;