Оператор без STL и ошибка «неверный оператор <» - PullRequest
14 голосов
/ 28 января 2012

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

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

Ответы [ 4 ]

27 голосов
/ 28 января 2012

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

  1. Нерефлексивность : x
  2. Антисимметрия : Если x
  3. Транзитивность : Если x
  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

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

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

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

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

5 голосов
/ 28 января 2012

@ 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;
3 голосов
/ 28 января 2012

@ 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>
    {
        /* ... */
    };
    }
    
0 голосов
/ 28 января 2012

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

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

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

...