STL减运算符和“无效运算符

问题描述 投票:14回答:4

我有一些代码可以在VS 10.0中编译好但是在下面的Orders地图中插入一些项目后,我在Microsoft调试库中收到“invalid operator <”错误。我的较少运算符很简单,只需将char字符串比较为8字节的字符串。任何人都知道为什么我会收到此错误?

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];
c++ dictionary stl strict-weak-ordering
4个回答
27
投票

我相信这里的问题是你比较两个MY_orderID_t的方法不是strict weak order,C ++ STL所需的排序关系的类型。要成为严格的弱订单,您的less-than运算符必须具有以下四个属性:

  1. 无反射性:x <x始终为假。
  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)并且应该使一切正常工作。

希望这可以帮助!


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;

3
投票

@templatetypedef从纯粹的语法角度解决了与std::less一起使用的map特化的要求:

  • 你需要qazxsw poi qazxsw poi和qazxsw poi
  • 你错过了下一行#include<functional>之间的<map>
  • 和: } 应该: char orderID[8];

0
投票

除了我目前没有看到的任何其他可能的错误,不允许使用此构造:

MY_orderID_t;

struct std::less<MY_orderID_t> { /* ... */ }; 已经是一种类型,所以你不能将它重新定义为另一种类型。

© www.soinside.com 2019 - 2024. All rights reserved.