【问题标题】:GUID as std::map keyGUID 作为 std::map 键
【发布时间】:2015-04-03 17:21:34
【问题描述】:

字典定义如下:

typedef boost::tuple<conn_ptr, handler_ptr, rdp_ptr> conn_tuple;
typedef std::map<GUID, conn_tuple> conn_map; 

我们遇到了编译错误:

错误 9 错误 C2678: 二进制 '

那么我们解决它为:

struct GUIDComparer
{
    bool operator()(const GUID & Left, const GUID & Right) const
    {
        // comparison logic goes here
        if( (Left.Data1 == Right.Data1) && (Left.Data2 == Right.Data2) && 
            (Left.Data3 == Right.Data3) && (memcmp(Left.Data4 , Right.Data4,sizeof(Right.Data4))==0)  )
        {   
            return true;
        }
        return false;
    }
};
typedef boost::tuple<conn_ptr, handler_ptr, rdp_ptr> conn_tuple;
typedef std::map<GUID, conn_tuple, GUIDComparer> conn_map; 

现在,全部编译好了,但是我们在运行时得到了一个异常(无效的操作符

我不知道哪里出了问题,如果有人可以帮助我会很高兴

【问题讨论】:

  • 另外,请注意&lt; 是“小于”,而不是“等于”。所以当memcmp() 返回小于零的值时返回true。你实现了错误的谓词,这就是你得到异常的原因。
  • @feras 请查看修改后的答案。上一个有一个重要的逻辑错误。

标签: c++ boost guid stdmap


【解决方案1】:

您的 GUIDComparer 正在比较是否相等。传递给 map 的函子必须生成弱排序 - 即它必须比较小或比较大,而不是相等。

这将起作用:

struct GUIDComparer
{
    bool operator()(const GUID & Left, const GUID & Right) const
    {
        // comparison logic goes here
        return memcmp(&Left , &Right,sizeof(Right)) < 0;
    }
};

【讨论】:

  • @RichardHodges:这好多了。如果GUID 中有填充字节,它仍然有可能被破坏。但我想 GUID 的大多数实现都没有填充字节。
  • 同意。我想我至少会得到逻辑上正确的解决方案(假设 GUID 是一个未填充的琐碎 POD 结构)。完全安全的解决方案是使用返回 -1、0 或 1 的 compare() 函数来编写 operator&lt;
  • 不知道,是否真的有必要在已经回答时提供代码?那教的是完全错误的事情。就像,一个人甚至不必尝试,只需去 SO 让其他人为您编写代码。
  • @Cheersandhth.-Alf 这不仅仅是关于 OP。我们不是“让我们帮助这个用户”服务(就像 ye olde forums/IRC)。考虑例如您的回答中没有提到 POD 和填充。
  • static_assert(std::is_pod&lt;GUID&gt;::value, "not applicable"); 的缺席甚至没有在答案中提到 POD 让我 -1 这个
【解决方案2】:

a 不等于b 比较时,显示的比较运算符可以为a&lt;bb&lt;a 返回false

只需将memcmp 应用于整个事情并检查结果。


附录(由于 sehe 的 cmets)。标记此问题的GUID 类型是标准 128 位 UUID 的 Windows API 名称,通用唯一标识符。它保证 POD,而且保证连续,因为它保证 128 位,每个位都有意义。这样可以安全地使用memcmp

【讨论】:

    【解决方案3】:

    您可以考虑使用 Boost.UUID 代替 Windows SDK 提供的 GUID。

    #include <boost/uuid/uuid.hpp>
    
    typedef std::map<boost::uuids::uuid, conn_tuple> conn_map;
    

    boost::uuids::uuid 已经提供了必要的比较运算符,因此您不必像其他答案中建议的那样编写排序谓词。

    【讨论】:

      【解决方案4】:
      struct GUIDComparer
      {
          bool operator()(const GUID & Left, const GUID & Right) const
          {enter code here
              // comparison logic goes here
              return memcmp(&Left , &Right,sizeof(Right)) < 0;
          }
      };
      
      sometimes this does not work.
      
      it should be: return memcmp(&Left , &Right,sizeof(Right)) == -1; (not 0)
      

      【讨论】:

      • 你能解释一下你做了什么,或者你是如何修复这个功能的吗?
      猜你喜欢
      • 2014-08-06
      • 2011-06-23
      • 1970-01-01
      • 2015-03-04
      • 1970-01-01
      • 1970-01-01
      • 2023-03-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多