首页 > 编程语言 >C++踩坑--set与重载<

C++踩坑--set与重载<

时间:2023-09-25 18:11:06浏览次数:39  
标签:std set Point -- c++ C++ include usr

set与重载<

set是有序容器,在定义容器的时候必须要指定 key 的比较函数。只不过这个函数通常是默认的 less,表示小于关系,不用特意写出来:

template<
    class Key,                      // 模板参数是key类型,即元素类型
    class Compare = std::less<Key>  // 比较函数
> class set;                        // 集合

C++ 里的 int、string 等基本类型都支持比较排序,放进有序容器里毫无问题。但很多自定义类型没有默认的比较函数,要作为容器的 key 就有点麻烦。虽然这种情况不多见,但有的时候还真是个“刚性需求”。解决这个问题一般是重载“<”,比如说我们有一个 Point 类,它是没有大小概念的,但只要给它重载“<”操作符,就可以放进有序容器里了:

/*************************************************************************
        > File Name: 03-set.cpp
        > Author:
        > Mail:
        > Created Time: Mon 25 Sep 2023 05:04:02 PM CST
 ************************************************************************/
#include <set>
#include <iostream>
using namespace std;

class Point
{
public:
    Point(double x, double y) : m_x(x), m_y(y) {}
    ~Point() {}
    bool operator < (const Point& rhs)
    {
        return m_x > rhs.m_x;
    }
private:
    double m_x, m_y;
};


int main()
{
    set<Point> s;
    s.emplace(Point(1.1, 2.2));
    s.emplace(Point(2.2, 3.3));
    return 0;
}

由于我是一个新手C++使用者,上述代码尽管重载了小于(<)运算符,但是编译报错:

ydqun@ydqhost chapter12 % g++ 03-set.cpp                                                                                                                                                                                            [0]
In file included from /usr/include/c++/9/bits/stl_tree.h:65,
                 from /usr/include/c++/9/set:60,
                 from 03-set.cpp:7:
/usr/include/c++/9/bits/stl_function.h: In instantiation of ‘constexpr bool std::less<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = Point]’:
/usr/include/c++/9/bits/stl_tree.h:2095:11:   required from ‘std::pair<std::_Rb_tree_node_base*, std::_Rb_tree_node_base*> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_get_insert_unique_pos(const key_type&) [with _Ke
y = Point; _Val = Point; _KeyOfValue = std::_Identity<Point>; _Compare = std::less<Point>; _Alloc = std::allocator<Point>; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::key_type = Point]’
/usr/include/c++/9/bits/stl_tree.h:2413:19:   required from ‘std::pair<std::_Rb_tree_iterator<_Val>, bool> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_emplace_unique(_Args&& ...) [with _Args = {Point}; _Key = Point;
 _Val = Point; _KeyOfValue = std::_Identity<Point>; _Compare = std::less<Point>; _Alloc = std::allocator<Point>]’
/usr/include/c++/9/bits/stl_set.h:463:64:   required from ‘std::pair<typename std::_Rb_tree<_Key, _Key, std::_Identity<_Tp>, _Compare, typename __gnu_cxx::__alloc_traits<_Alloc>::rebind<_Key>::other>::const_iterator, bool> std::set<
_Key, _Compare, _Alloc>::emplace(_Args&& ...) [with _Args = {Point}; _Key = Point; _Compare = std::less<Point>; _Alloc = std::allocator<Point>; typename std::_Rb_tree<_Key, _Key, std::_Identity<_Tp>, _Compare, typename __gnu_cxx::__
alloc_traits<_Alloc>::rebind<_Key>::other>::const_iterator = std::_Rb_tree_const_iterator<Point>]’
03-set.cpp:28:30:   required from here
/usr/include/c++/9/bits/stl_function.h:386:20: error: no match for ‘operator<’ (operand types are ‘const Point’ and ‘const Point’)
  386 |       { return __x < __y; }
      |                ~~~~^~~~~
03-set.cpp:16:10: note: candidate: ‘bool Point::operator<(const Point&)’ <near match>
   16 |     bool operator < (const Point& rhs)
      |          ^~~~~~~~
03-set.cpp:16:10: note:   passing ‘const Point*’ as ‘this’ argument discards qualifiers
In file included from /usr/include/c++/9/bits/stl_algobase.h:64,
                 from /usr/include/c++/9/bits/stl_tree.h:63,
                 from /usr/include/c++/9/set:60,
                 from 03-set.cpp:7:
/usr/include/c++/9/bits/stl_pair.h:454:5: note: candidate: ‘template<class _T1, class _T2> constexpr bool std::operator<(const std::pair<_T1, _T2>&, const std::pair<_T1, _T2>&)’
  454 |     operator<(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
      |     ^~~~~~~~
/usr/include/c++/9/bits/stl_pair.h:454:5: note:   template argument deduction/substitution failed:
In file included from /usr/include/c++/9/bits/stl_tree.h:65,
                 from /usr/include/c++/9/set:60,
                 from 03-set.cpp:7:
/usr/include/c++/9/bits/stl_function.h:386:20: note:   ‘const Point’ is not derived from ‘const std::pair<_T1, _T2>’
  386 |       { return __x < __y; }
      |                ~~~~^~~~~
In file included from /usr/include/c++/9/bits/stl_algobase.h:67,
                 from /usr/include/c++/9/bits/stl_tree.h:63,
                 from /usr/include/c++/9/set:60,
                 from 03-set.cpp:7:
/usr/include/c++/9/bits/stl_iterator.h:331:5: note: candidate: ‘template<class _Iterator> bool std::operator<(const std::reverse_iterator<_Iterator>&, const std::reverse_iterator<_Iterator>&)’
...... 中间省略若几十行(无力吐槽C++编译出错提示)
/usr/include/c++/9/bits/stl_function.h:386:20: note:   ‘const Point’ is not derived from ‘const std::__cxx11::basic_string<_CharT, _Traits, _Alloc>’
  386 |       { return __x < __y; }
      |                ~~~~^~~~~
In file included from /usr/include/c++/9/string:55,
                 from /usr/include/c++/9/bits/locale_classes.h:40,
                 from /usr/include/c++/9/bits/ios_base.h:41,
                 from /usr/include/c++/9/ios:42,
                 from /usr/include/c++/9/ostream:38,
                 from /usr/include/c++/9/iostream:39,
                 from 03-set.cpp:8:
/usr/include/c++/9/bits/basic_string.h:6239:5: note: candidate: ‘template<class _CharT, class _Traits, class _Alloc> bool std::operator<(const std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&, const _CharT*)’
 6239 |     operator<(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
      |     ^~~~~~~~
/usr/include/c++/9/bits/basic_string.h:6239:5: note:   template argument deduction/substitution failed:
In file included from /usr/include/c++/9/bits/stl_tree.h:65,
                 from /usr/include/c++/9/set:60,
                 from 03-set.cpp:7:
/usr/include/c++/9/bits/stl_function.h:386:20: note:   ‘const Point’ is not derived from ‘const std::__cxx11::basic_string<_CharT, _Traits, _Alloc>’
  386 |       { return __x < __y; }
      |                ~~~~^~~~~
In file included from /usr/include/c++/9/string:55,
                 from /usr/include/c++/9/bits/locale_classes.h:40,
                 from /usr/include/c++/9/bits/ios_base.h:41,
                 from /usr/include/c++/9/ios:42,
                 from /usr/include/c++/9/ostream:38,
                 from /usr/include/c++/9/iostream:39,
                 from 03-set.cpp:8:
/usr/include/c++/9/bits/basic_string.h:6251:5: note: candidate: ‘template<class _CharT, class _Traits, class _Alloc> bool std::operator<(const _CharT*, const std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&)’
 6251 |     operator<(const _CharT* __lhs,
      |     ^~~~~~~~
/usr/include/c++/9/bits/basic_string.h:6251:5: note:   template argument deduction/substitution failed:
In file included from /usr/include/c++/9/bits/stl_tree.h:65,
                 from /usr/include/c++/9/set:60,
                 from 03-set.cpp:7:
/usr/include/c++/9/bits/stl_function.h:386:20: note:   mismatched types ‘const _CharT*’ and ‘Point’
  386 |       { return __x < __y; }
      |                ~~~~^~~~~
In file included from /usr/include/c++/9/bits/ios_base.h:46,
                 from /usr/include/c++/9/ios:42,
                 from /usr/include/c++/9/ostream:38,
                 from /usr/include/c++/9/iostream:39,
                 from 03-set.cpp:8:
/usr/include/c++/9/system_error:208:3: note: candidate: ‘bool std::operator<(const std::error_code&, const std::error_code&)’
  208 |   operator<(const error_code& __lhs, const error_code& __rhs) noexcept
      |   ^~~~~~~~
/usr/include/c++/9/system_error:208:31: note:   no known conversion for argument 1 from ‘const Point’ to ‘const std::error_code&’
  208 |   operator<(const error_code& __lhs, const error_code& __rhs) noexcept
      |             ~~~~~~~~~~~~~~~~~~^~~~~
/usr/include/c++/9/system_error:282:3: note: candidate: ‘bool std::operator<(const std::error_condition&, const std::error_condition&)’
  282 |   operator<(const error_condition& __lhs,
      |   ^~~~~~~~
/usr/include/c++/9/system_error:282:36: note:   no known conversion for argument 1 from ‘const Point’ to ‘const std::error_condition&’
  282 |   operator<(const error_condition& __lhs,
      |             ~~~~~~~~~~~~~~~~~~~~~~~^~~~~

相信不少新入坑C++的同学看到这类报错后头都大了(我也是)。
经过我长达半个小时的排查,终于从出错提示中找到答案,在报错信息中的第四行,如下:

/usr/include/c++/9/bits/stl_function.h: In instantiation of ‘constexpr bool std::less<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = Point]’:

这时候,我们可以知道是因为在类内重载<运算符时,少了const修饰,导致函数签名不匹配,我们只需要对重载的operator<()函数后面加上const修饰,即可解决,完整代码如下:

/*************************************************************************
        > File Name: 03-set.cpp
        > Author:
        > Mail:
        > Created Time: Mon 25 Sep 2023 05:04:02 PM CST
 ************************************************************************/
#include <set>
#include <iostream>
using namespace std;

class Point
{
public:
    Point(double x, double y) : m_x(x), m_y(y) {}
    ~Point() {}
    bool operator < (const Point& rhs) const
    {
        return m_x > rhs.m_x;
    }
private:
    double m_x, m_y;
};


int main()
{
    set<Point> s;
    s.emplace(Point(1.1, 2.2));
    s.emplace(Point(2.2, 3.3));
    return 0;
}

标签:std,set,Point,--,c++,C++,include,usr
From: https://www.cnblogs.com/ydqblogs/p/17728529.html

相关文章

  • 低代码引擎 TinyEngine 正式发布!
    在当今数字化飞速发展的时代,企业对高效、敏捷的应用程序需求日益旺盛。为了满足这一需求,越来越多的低代码开发平台开始涌现。这些平台通过提供简单易用的开发工具和优化后的开发流程,帮助开发者快速构建高质量、可重复使用的应用程序,同时降低了开发的难度和成本,提高了开发效率和灵......
  • 道情十首---[清]郑板桥
    郑板桥《道情十首》━━━━━━━━━━━━━━━━━━━━━━道情十首---[清]郑板桥(石块无多竹叶稀,二公清介最可依;秋风昨夜窗前到,百岁苍苔老更肥。)[引子]枫叶芦花并客舟,烟波江上使人愁;劝君更尽一杯酒,昨日少年今白头。自家板桥道人是也,我先世元和公公,流落人间教歌度......
  • 04. 路由控制
    一、简单配置  URL配置的本质是URL与要为该URL调用的视图函数之间的映射表。通过这种方式告诉Django,对于客户端发过来的某个URL调用哪一段逻辑代码执行。  用户通过在浏览器中输入URL和单击链接来请求网页,因此需要确定项目需要哪些URL。我们新建一个Django项......
  • 19-内置指令
    目前为止,我们学过的指令:v-bind:单向绑定解析表达式,可以简写为 :xxxv-model:双向数据绑定v-for:遍历数组/对象/字符串v-on:绑定事件监听,可以简写为@v-if:条件渲染(动态控制节点是否存在)v-else:条件渲染(动态控制节点是否存在)v-show:条件渲染(动态控制节点是否展示) v-text指......
  • 使用json+echarts实现数据库数据的可视化
    因为我上次是使用的另外一种方法实现的可视化,对json了解的不够,所以来补充一下这一块的知识点1、新建一个SpringBoot项目2、添加依赖<dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId></dependency><d......
  • HarmonyOS使用多线程并发能力开发
     一、多线程并发概述1、简介并发模型是用来实现不同应用场景中并发任务的编程模型,常见的并发模型分为基于内存共享的并发模型和基于消息通信的并发模型。Actor并发模型作为基于消息通信并发模型的典型代表,不需要开发者去面对锁带来的一系列复杂偶发的问题,同时并发度也相对......
  • 口算题卡代码
    8.(简答题)请完善课上的口算题卡代码,实现重复题目的检测、题目数字范围、加减乘除算式的参数化等扩展功能,提交代码和运行截图。packageorg.example;importjava.util.Random;importjava.util.Scanner;publicclassMain{publicstaticvoidmain(String[]args)......
  • 叶片包角及安放角的图解
    叶片包角及安放角的图解–泵小丫(7b3.cn)在叶片设计过程中,叶片包角和叶片进、出口安放角是很重要的参数。我们先来看看这些参数具体指什么?首先需要明确一点,这些参数都是针对叶片工作面的,叶片背面是靠加厚规律得到的,我们在设计叶轮时重点在于设计工作面。叶片包角包角......
  • abc321记录
    SuntoryProgrammingContest2023(AtCoderBeginnerContest321)-AtCoderD题意:给定常数\(k\)和长度为\(n\)的数组\(a\)和长度为\(m\)的数组\(b\),求\(\sum_{i=1}^n\sum_{j=1}^mmin\{a_i+b_j,k\}\)。数据范围:\(n,m\le2\times10^5\)tag:二分前缀和枚举\(a_i\),在......
  • 9.25
    今天完成软件构造作业,写一个自动出题程序。package软件构造;importjava.util.HashMap;importjava.util.Map;importjava.util.Random;publicclassTest{privatestaticfinalintMIN_NUMBER=1;//最小数字范围privatestaticfinalintMAX_NUMBER=100;//......