14

我有一些代码在 VS 10.0 中编译得很好,但是在下面的 Orders 映射中插入了一些项目后,我在 Microsoft 调试库中收到“无效的运算符 <”错误。我的 less 运算符很简单,只是将 8 字节字符串 char 逐个比较。有人知道为什么我会收到此错误吗?

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

4 回答 4

27

我相信这里的问题是您比较两个MY_orderID_t的方法不是严格的弱顺序,即C++ STL所需的排序关系类型。要成为严格的弱顺序,您的小于运算符必须具有以下四个属性:

  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

要解决此问题,请不要使用您当前拥有的比较,而是使用像这样的字典比较

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

这种比较是严格的弱排序,并且是所有 STL 容器默认使用的。切换到此比较遵循属性 (1) - (4),并且应该使一切正常工作。

希望这可以帮助!

于 2012-01-27T22:14:55.827 回答
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;
于 2012-01-27T22:19:45.933 回答
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>
    {
        /* ... */
    };
    }
    
于 2012-01-27T22:19:10.340 回答
0

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

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

std::less已经是一种类型,因此您不能将其重新定义为另一种类型。

于 2012-01-27T22:10:59.620 回答