C++ 如果没有定义比较运算符的逻辑方法,如何将自定义类用作std::map的键?

C++ 如果没有定义比较运算符的逻辑方法,如何将自定义类用作std::map的键?,c++,C++,我试图将std::map与一个自定义类一起使用,在这个过程中,程序必须调用std::map::find来解析一对密钥。自定义类在比较方面似乎不太合适 这可能在代码中得到更好的解释;我有一个要用作键的类: class index_t { int vertex_index; int normal_index; int texture_index; } std::map<index_t, int> reindexer

我试图将std::map与一个自定义类一起使用,在这个过程中,程序必须调用std::map::find来解析一对密钥。自定义类在比较方面似乎不太合适

这可能在代码中得到更好的解释;我有一个要用作键的类:

 class index_t
    {
       int vertex_index;
       int normal_index;
       int texture_index;
     }

     std::map<index_t, int> reindexer;
为了找到具有完全相同参数(完全相同的顶点/法线/纹理索引)的关键点,贴图中已经存在

从技术上讲,我希望std::map::find函数的行为如下:

bool find(key_to_find) //this is what I'm expecting from a find function of std::map
{
    if(existing_key.vertex == key_to_find.vertex && existing_key.texture == key_to_find.texture && existing_key.normal == key_to_find.normal)
         return true;
    else return false;
}
但是,我不确定在这种情况下如何适当地重载比较运算符,使其表现为那样(因为我可以想出适合此类的逻辑小于运算符)。这是我正在使用的当前运算符:

   bool operator<(const index_t& rhv)
   {
     if(vertex_index < rhv && normal_index < rhv && texture_index < rhv)
       return true;
     else return false;
    }

bool操作符您必须定义一个严格的顺序,才能将
class index\u t
用作
std::map
中的键

它不需要对您有意义–它只需要提供一个小于任何一对
index\u t
实例的唯一结果(并授予aa (有问题的)暴露尝试似乎无法实现这一点,但以下示例将:

bool operator<(const index_t &index1, const index_t &index2)
{
  if (index1.vertex != index2.vertex) return index1.vertex < index2.vertex;
  if (index1.normal != index2.normal) return index1.normal < index2.normal;
  return index1.texture < index2.texture;
}

bool操作符您必须定义一个严格的顺序,才能将
class index\u t
用作
std::map
中的键

它不需要对您有意义–它只需要提供一个小于任何一对
index\u t
实例的唯一结果(并授予aa (有问题的)暴露尝试似乎无法实现这一点,但以下示例将:

bool operator<(const index_t &index1, const index_t &index2)
{
  if (index1.vertex != index2.vertex) return index1.vertex < index2.vertex;
  if (index1.normal != index2.normal) return index1.normal < index2.normal;
  return index1.texture < index2.texture;
}

bool操作符您的比较函数不必是逻辑函数,它只需施加一个。这是一个有效的版本

bool operator<(const index_t& rhv) const
{
    if (vertex < rhv.vertex)
        return true;
    if (vertex > rhv.vertex)
        return false;
    if (normal < rhv.normal)
        return true;
    if (normal > rhv.normal)
        return false;
    if (texture < rhv.texture)
        return true;
    if (texture > rhv.texture)
        return false;
    return false;
}
然后像这样使用这个新声明的函子

std::map<index_t, whatever, IndexLT> my_map;
std::map my\u map;

另一种选择是使用
std::unordered_map
,因为排序似乎并不重要。

您的比较函数不必是逻辑的,它只需要强制一个。这是一个有效的版本

bool operator<(const index_t& rhv) const
{
    if (vertex < rhv.vertex)
        return true;
    if (vertex > rhv.vertex)
        return false;
    if (normal < rhv.normal)
        return true;
    if (normal > rhv.normal)
        return false;
    if (texture < rhv.texture)
        return true;
    if (texture > rhv.texture)
        return false;
    return false;
}
然后像这样使用这个新声明的函子

std::map<index_t, whatever, IndexLT> my_map;
std::map my\u map;

另一种选择是使用
std::unordered_map
,因为排序似乎并不重要。

您的排序不符合要求,必须是所谓的“严格弱排序关系”。最好不要自己实现,而是使用现有的功能。例如:

#include <tuple>

bool operator()(const index_t& lhv, const index_t& rhv) const
{
    return std::tie(lhv.vertex, lhv.normal, lhv.texture) <
       std::tie(rhv.vertex, rhv.normal, rhv.texture);
}
#包括
布尔运算符()
{
return std::tie(左上角顶点、左下角法线、左下角纹理)<
标准::领带(rhv顶点、rhv法线、rhv纹理);
}

您的订购不符合要求,必须是所谓的“严格弱订购关系”。最好不要自己实现,而是使用现有的功能。例如:

#include <tuple>

bool operator()(const index_t& lhv, const index_t& rhv) const
{
    return std::tie(lhv.vertex, lhv.normal, lhv.texture) <
       std::tie(rhv.vertex, rhv.normal, rhv.texture);
}
#包括
布尔运算符()
{
return std::tie(左上角顶点、左下角法线、左下角纹理)<
标准::领带(rhv顶点、rhv法线、rhv纹理);
}

实现运算符的最简单方法是使用元组,它可以为您完成所有艰巨的工作:

bool operator<(const index_t& rhv)
{
   return std::tie(vertex_index, normal_index, texture_index) < std::tie(rhv.vertex_index, rhv.normal_index, rhv.texture_index);
}

bool操作符实现该操作符的最简单方法是使用元组,它可以为您完成所有艰苦的工作:

bool operator<(const index_t& rhv)
{
   return std::tie(vertex_index, normal_index, texture_index) < std::tie(rhv.vertex_index, rhv.normal_index, rhv.texture_index);
}

bool运算符使用
std::tie()
通常在这种情况下有效。但是如果你不需要特定的顺序,你应该考虑<代码> STD::unOrdEdEdMult/Cuth>,因为它会更有效。@斯拉瓦为<代码> STD::unOrdEdEdMult/<代码>,<代码> STD::hash()//> >必须重载。@ sHeff-Yes,但是为3个int实现哈希是相当微不足道的。这里有很多例子。@Slava当然…;-)在这种情况下,通常使用
std::tie()
。但是如果你不需要特定的顺序,你应该考虑<代码> STD::unOrdEdEdMult/Cuth>,因为它会更有效。@斯拉瓦为<代码> STD::unOrdEdEdMult/<代码>,<代码> STD::hash()//> >必须重载。@ sHeff-Yes,但是为3个int实现哈希是相当微不足道的。这里有很多例子。@Slava当然…;-)谢谢这是为我做的,加上c++20操作数,以防我切换到它。谢谢!,这是为我做的,加上c++20操作数,以防我切换到它。
auto operator<=>(const index_t&) const = default;