You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确使用C++中set的.find()函数?自定义point结构体引发匹配错误

问题描述

定义了如下point结构体:

struct point
{
  double x;
  double y;
};

编写isChecked函数时,使用set<vector<point>>的.find()函数出现错误,鼠标悬停提示In template: invalid operands to binary expression ('const point' and 'const point'),函数代码如下:

bool isChecked(point left, point right, set<vector<point>>const& inSet)
{
  // 检查点的两种排列组合
  vector<point> tmp1 = {left, right};
  vector<point> tmp2 = {right, left};

  // .find()返回找到元素的迭代器,未找到则返回.end()
  auto first = inSet.find(tmp1);
  auto second = inSet.find(tmp2);

  // 判断是否已检查过该点对
  if (first != inSet.end() || second != inSet.end())
      return true;

  return false;
}

编译器给出的错误信息:

C:/msys64/mingw64/include/c++/12.2.0/bits/predefined_ops.h:45:23: error: no match for 'operator<' (operand types are 'const point' and 'const point')
   45 |       { return *__it1 < *__it2; }
      |                ~~~~~~~^~~~~~~~
In file included from C:/msys64/mingw64/include/c++/12.2.0/string:47:
C:/msys64/mingw64/include/c++/12.2.0/bits/stl_iterator.h:1246:5: note: candidate: 'template<class _IteratorL, class _IteratorR, class _Container> bool __gnu_cxx::operator<(const __normal_iterator<_IteratorL, _Container>&, const __normal_iterator<_IteratorR, _Container>&)' 
 1246 |     operator<(const __normal_iterator<_IteratorL, _Container>& __lhs,
      |     ^~~~~~~~
C:/msys64/mingw64/include/c++/12.2.0/bits/stl_iterator.h:1246:5: note:   template argument deduction/substitution failed:
C:/msys64/mingw64/include/c++/12.2.0/bits/predefined_ops.h:45:23: note:   'const point' is not derived from 'const __gnu_cxx::__normal_iterator<_IteratorL, _Container>'
   45 |       { return *__it1 < *__it2; }
      |                ~~~~~~~^~~~~~~~
C:/msys64/mingw64/include/c++/12.2.0/bits/stl_iterator.h:1254:5: note: candidate: 'template<class _Iterator, class _Container> bool __gnu_cxx::operator<(const __normal_iterator<_Iterator, _Container>&, const __normal_iterator<_Iterator, _Container>&)' 
 1254 |     operator<(const __normal_iterator<_Iterator, _Container>& __lhs,
      |     ^~~~~~~~
C:/msys64/mingw64/include/c++/12.2.0/bits/stl_iterator.h:1254:5: note:   template argument deduction/substitution failed:
C:/msys64/mingw64/include/c++/12.2.0/bits/predefined_ops.h:45:23: note:   'const point' is not derived from 'const __gnu_cxx::__normal_iterator<_Iterator, _Container>'
   45 |       { return *__it1 < *__it2; }
      |                ~~~~~~~^~~~~~~~
ninja: build stopped: subcommand failed.
错误原因

C++标准库的set是有序容器,默认依赖<运算符完成元素排序和比较。对于set<vector<point>>,比较逻辑会递归到vector内部的元素——也就是point对象,但自定义的point结构体没有重载<运算符,编译器无法判断两个point的大小关系,导致.find()调用失败。

解决方案

有三种可行的解决方式:

方法一:为point重载<运算符

直接在point结构体中定义operator<,实现明确的比较逻辑(比如先比x坐标,x相等再比y坐标):

struct point
{
  double x;
  double y;

  // 重载小于运算符,必须是const成员函数
  bool operator<(const point& other) const
  {
      if (x != other.x)
          return x < other.x;
      return y < other.y;
  }
};

完成后,vector<point>的比较会自动使用该运算符,set的.find()即可正常工作。

方法二:给set传入自定义比较器

如果不想修改point结构体,可以定义独立的比较规则,作为set的模板参数:

// 自定义比较器结构体
struct PointVectorCompare
{
    bool operator()(const vector<point>& a, const vector<point>& b) const
    {
        if (a.size() != b.size())
            return a.size() < b.size();
        // 逐个比较vector中的point元素
        for (size_t i = 0; i < a.size(); ++i)
        {
            if (a[i].x != b[i].x)
                return a[i].x < b[i].x;
            if (a[i].y != b[i].y)
                return a[i].y < b[i].y;
        }
        return false;
    }
};

// 使用自定义比较器声明set
set<vector<point>, PointVectorCompare> inSet;

这种方式无需改动point本身,直接为set指定专属的比较逻辑。

方法三:改用unordered_set(需定义哈希与相等规则)

如果不需要有序存储,可以改用基于哈希的unordered_set,但需要为point和vector<point>分别定义==运算符和哈希函数:

struct point
{
  double x;
  double y;

  // 重载相等运算符
  bool operator==(const point& other) const
  {
      return x == other.x && y == other.y;
  }
};

// 为point定义哈希函数
namespace std
{
    template<> struct hash<point>
    {
        size_t operator()(const point& p) const
        {
            // 组合x和y的哈希值,可根据需求调整实现
            size_t hash_x = hash<double>()(p.x);
            size_t hash_y = hash<double>()(p.y);
            return hash_x ^ (hash_y << 1);
        }
    };

    // 为vector<point>定义哈希函数
    template<> struct hash<vector<point>>
    {
        size_t operator()(const vector<point>& vec) const
        {
            size_t result = 0;
            for (const auto& p : vec)
            {
                result ^= hash<point>()(p) + 0x9e3779b9 + (result << 6) + (result >> 2);
            }
            return result;
        }
    };
}

// 使用unordered_set
unordered_set<vector<point>> inSet;

注意:浮点数存在精度问题,如果x/y可能有精度误差,建议先做截断或取整处理再计算哈希。

另外,从你的函数逻辑来看,可优化点对的存储方式:插入集合时统一存储有序点对(比如始终把x较小的点放在前面,x相等则y较小的在前),这样查找时只需生成一个有序vector,无需两次查找,能提升效率。


内容的提问来源于stack exchange,提问作者Jack Hermanson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 10:02:23