STL меньше оператора и ошибка "неправильный оператор <"
У меня есть код, который отлично компилируется в VS 10.0, но после вставки нескольких элементов на карту Заказов ниже я получаю "недопустимый оператор <" ошибка в библиотеке отладки Microsoft. Мой меньший оператор прост, просто сравнивает 8-байтовую строку char на char. У кого-нибудь есть идея, почему я получаю эту ошибку?
Спасибо,
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];
Ответы
Ответ 1
Я считаю, что проблема в том, что ваш метод сравнения двух MY_orderID_t
не является строгим слабым порядком, тип отношения упорядочения, требуемый С++ STL. Чтобы быть строгим слабым порядком, ваш менее чем оператор должен иметь следующие четыре свойства:
- Irreflexivity: x < x всегда false.
- Антисимметрия: если x < y, то y < x всегда false.
- Транзитивность: если x < y и y < z, то x < z всегда истинно.
- Транзитивность эквивалентности: если 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) и должно заставить все работать правильно.
Надеюсь, это поможет!
Ответ 2
@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
@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>
{
/* ... */
};
}
Ответ 4
Помимо любых других возможных ошибок, которые я не вижу на данный момент, эта конструкция не допускается:
struct std::less<MY_orderID_t>
{ /**/ }
std::less
уже является типом, поэтому вы не можете переопределить его как другой тип.