2012-01-27 3 views
14

У меня есть код, который компилируется в VS 10.0, но после вставки нескольких элементов на карту Заказов ниже я получаю ошибку «ошибка <» в библиотеке отладки Microsoft. Мой меньший оператор прост, просто сравнивает 8-байтовый строковый символ char. У кого-нибудь есть идея, почему я получу эту ошибку?Ошибка оператора STL и «неверный оператор <»

Спасибо, Майк

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]; 

ответ

0

Помимо других возможных ошибок, которые я не вижу на данный момент, эта конструкция не допускается:

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

std::less уже типа, поэтому вы не можете переопределить его как другой тип.

+0

И [это другое сообщение] (http://stackoverflow.com/questions/2282349/specialization-of-templateclass-tp-struct-stdless-in- other-namespace) показывает правильный способ специализации 'std :: less'. –

27

Я считаю, что проблема здесь заключается в том, что ваш метод сравнения двух MY_orderID_t «S не strict weak order, тип заказа отношения требуемого C++ STL. Для того, чтобы быть строгим слабый порядок, ваш менее чем оператор должен иметь следующие четыре свойства:

  1. Irreflexivity: х < х всегда ложно.
  2. Антисимметрия: Если x < y, то y < x всегда неверно.
  3. Транзитивность: Если x < y и y < z, то x < z всегда верно.
  4. Транзитивность эквивалентности: Если x и y несравнимы, а y и z несравнимы, то x и z несравнимы.

Прямо сейчас, ваш заказ не соответствует свойствам (2) или (3).

* Во-первых, (2) нарушается следующее:

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

* Во-вторых, (3) нарушается, потому что

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

// but 

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

Чтобы исправить это, вместо того, чтобы использовать сравнение вам в настоящее время, вместо того, чтобы использовать lexicographical comparison как это одна:

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

Это сравнение является строгим слабым порядком, и это то, что используется всеми контейнерами STL по умолчанию. Переключение на это сравнение подчиняется свойствам (1) - (4) и должно заставить все работать правильно.

Надеюсь, это поможет!

+0

Для получения дополнительной информации см. Эту замечательную статью: [Заказать я говорю!] (Http://cpp-next.com/archive/2010/02/order-i-say/). – ildjarn

3

@templatetypedef рассматривается требование к std::less специализации для использования с map, с чисто синтаксической точки зрения:

  • Вы должны #include<functional> и <map>

  • Вы отсутствующий } между char orderID[8]; и MY_orderID_t; на следующей строке.

  • и:

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

    должно быть:

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

@templatetypedef говорит вам, что случилось с вашей текущей версии.

Вот намного более читаемым исправление:

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; 
Смежные вопросы