【问题标题】:STL less operator and "invalid operator<" errorSTL 少运算符和“无效运算符<”错误
【发布时间】:2012-02-20 21:05:22
【问题描述】:

我有一些代码在 VS 10.0 中编译得很好,但是在下面的 Orders 映射中插入一些项目后,我在 Microsoft 调试库中收到“无效的运算符

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


    【解决方案1】:

    我认为这里的问题是您比较两个MY_orderID_t 的方法不是strict weak order,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
    

    要解决此问题,请不要使用您当前的比较,而是使用 lexicographical comparison,如下所示:

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

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

    希望这会有所帮助!

    【讨论】:

    • 更多详情,请看这篇优秀的文章:Order I Say!
    【解决方案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&lt;functional&gt;&lt;map&gt;

      • 您在下一行的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 已经是一个类型,所以你不能将它重新定义为另一个类型。

        【讨论】:

        猜你喜欢
        • 2013-07-07
        • 1970-01-01
        • 2015-09-10
        • 1970-01-01
        • 2012-07-19
        • 2014-10-05
        • 1970-01-01
        • 1970-01-01
        • 2011-02-08
        相关资源
        最近更新 更多