STL less运算符和“invalid operator<”错误

时间:2012-01-27 22:05:19

标签: c++ dictionary stl strict-weak-ordering

我有一些代码可以在VS 10.0中编译好但是在下面的Orders地图中插入几个项目后,我收到一个“无效的运算符<” Microsoft调试库中的错误。我的较少运算符很简单,只需将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];

4 个答案:

答案 0 :(得分:27)

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

  1. 反身性:x&lt; x总是假的。
  2. 反对称:如果x&lt; y,然后y&lt; x总是假的。
  3. 传递性:如果x&lt; y和y&lt; z,然后x&lt; z总是如此。
  4. 等价的传递性:如果x和y无法比较且y和z无法比拟,那么x和z是无法比拟的。
  5. 现在,您的订购不遵守属性(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)并且应该使一切正常工作。

    希望这有帮助!

答案 1 :(得分: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;

答案 2 :(得分:3)

@templatetypedef从纯粹的语法角度阐述了std::lessmap一起使用的专业化的要求:

  • 您需要#include <functional><map>

  • 您在下一行的}char orderID[8];之间遗漏了MY_orderID_t;

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

    应该是:

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

答案 3 :(得分:0)

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

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

std::less已经是一种类型,因此您无法将其重新定义为其他类型。