STL中map容器使用自定义key类型报错详解

一篇带你了解STL-set和map的基本使用 set和map关联式容器键值对树形结构的关联式容器setset的构造set的插入和迭代器set的容量set的删除multisetmap二级标题二级标题二级标题二级标题三级目录 关联式容器 之前遇到的vector,list,deque这些容器统称为序列式容器,因为其底层为线性序列的数据结构,里面存储的是元素本身。 关联式容器: 用来存储数据的,与序列式容器不同的是,其里面存储的是<key, value>结构的键值对,在 数据检索时比序列式容器效率更高。 键值对 用来表示具有一一对应关系的一种结 阅读详情

引言

STL的map容器中,key的类型是不是随意的呢?

实践

编写测试代码

定义一个结构体来试试:

struct a
{
	char* pName;
	int m_a;
	
};
map<a, int> mp;
	a a1;
	a1.m_a		= 100;
	a1.pName	= "a1";
	a a2;
	a2.m_a		= 200;
	a2.pName	= "a2";
	mp.insert(std::make_pair(a1, 1));
	mp.insert(std::make_pair(a2, 1));

编译出错

初始化结构体对象,添加到容器中,编译程序:

f:\vs2008\vc\include\functional(143) : error C2784: “bool std::operator <(const std::_Tree<_Traits> &,const std::_Tree<_Traits> &)”: 无法从“const a”为“const std::_Tree<_Traits> &”推导 模板 参数
1>        f:\vs2008\vc\include\xtree(1466) : 参见“std::operator <”的声明
1>        f:\vs2008\vc\include\functional(142): 编译类 模板 成员函数“bool std::less<_Ty>::operator ()(const _Ty &,const _Ty &) const”时
1>        with
1>        [
1>            _Ty=a
1>        ]
1>        f:\vs2008\vc\include\map(68): 参见对正在编译的类 模板 实例化“std::less<_Ty>”的引用
1>        with
1>        [
1>            _Ty=a
1>        ]
1>        f:\vs2008\vc\include\xtree(22): 参见对正在编译的类 模板 实例化“std::_Tmap_traits<_Kty,_Ty,_Pr,_Alloc,_Mfl>”的引用
1>        with
1>        [
1>            _Kty=a,
1>            _Ty=int,
1>            _Pr=std::less<a>,
1>            _Alloc=std::allocator<std::pair<const a,int>>,
1>            _Mfl=false
1>        ]
1>        f:\vs2008\vc\include\xtree(63): 参见对正在编译的类 模板 实例化“std::_Tree_nod<_Traits>”的引用
1>        with
1>        [
1>            _Traits=std::_Tmap_traits<a,int,std::less<a>,std::allocator<std::pair<const a,int>>,false>
1>        ]
1>        f:\vs2008\vc\include\xtree(89): 参见对正在编译的类 模板 实例化“std::_Tree_ptr<_Traits>”的引用
1>        with
1>        [
1>            _Traits=std::_Tmap_traits<a,int,std::less<a>,std::allocator<std::pair<const a,int>>,false>
1>        ]
1>        f:\vs2008\vc\include\xtree(107): 参见对正在编译的类 模板 实例化“std::_Tree_val<_Traits>”的引用
1>        with
1>        [
1>            _Traits=std::_Tmap_traits<a,int,std::less<a>,std::allocator<std::pair<const a,int>>,false>
1>        ]
1>        f:\vs2008\vc\include\map(78): 参见对正在编译的类 模板 实例化“std::_Tree<_Traits>”的引用
1>        with
1>        [
1>            _Traits=std::_Tmap_traits<a,int,std::less<a>,std::allocator<std::pair<const a,int>>,false>
1>        ]
1>        f:\fileoprate\fileoprate\fileoprate.cpp(49): 参见对正在编译的类 模板 实例化“std::map<_Kty,_Ty>”的引用
1>        with
1>        [
1>            _Kty=a,
1>            _Ty=int
1>        ]
1>f:\vs2008\vc\include\functional(143) : error C2784: “bool std::operator <(const std::vector<_Ty,_Alloc> &,const std::vector<_Ty,_Alloc> &)”: 无法从“const a”为“const std::vector<_Ty,_Alloc> &”推导 模板 参数
1>        f:\vs2008\vc\include\vector(1320) : 参见“std::operator <”的声明
1>f:\vs2008\vc\include\functional(143) : error C2784: “bool std::operator <(const std::basic_string<_Elem,_Traits,_Alloc> &,const _Elem *)”: 无法从“const a”为“const std::basic_string<_Elem,_Traits,_Alloc> &”推导 模板 参数
1>        f:\vs2008\vc\include\string(150) : 参见“std::operator <”的声明
1>f:\vs2008\vc\include\functional(143) : error C2784: “bool std::operator <(const _Elem *,const std::basic_string<_Elem,_Traits,_Alloc> &)”: 无法从“const a”为“const _Elem *”推导 模板 参数
1>        f:\vs2008\vc\include\string(140) : 参见“std::operator <”的声明
1>f:\vs2008\vc\include\functional(143) : error C2784: “bool std::operator <(const std::basic_string<_Elem,_Traits,_Alloc> &,const std::basic_string<_Elem,_Traits,_Alloc> &)”: 无法从“const a”为“const std::basic_string<_Elem,_Traits,_Alloc> &”推导 模板 参数
1>        f:\vs2008\vc\include\string(130) : 参见“std::operator <”的声明
1>f:\vs2008\vc\include\functional(143) : error C2784: “bool std::operator <(const std::reverse_iterator<_RanIt> &,const std::reverse_iterator<_RanIt2> &)”: 无法从“const a”为“const std::reverse_iterator<_RanIt> &”推导 模板 参数
1>        f:\vs2008\vc\include\xutility(2236) : 参见“std::operator <”的声明
1>f:\vs2008\vc\include\functional(143) : error C2784: “bool std::operator <(const std::_Revranit<_RanIt,_Base> &,const std::_Revranit<_RanIt2,_Base2> &)”: 无法从“const a”为“const std::_Revranit<_RanIt,_Base> &”推导 模板 参数
1>        f:\vs2008\vc\include\xutility(2046) : 参见“std::operator <”的声明
1>f:\vs2008\vc\include\functional(143) : error C2784: “bool std::operator <(const std::pair<_Ty1,_Ty2> &,const std::pair<_Ty1,_Ty2> &)”: 无法从“const a”为“const std::pair<_Ty1,_Ty2> &”推导 模板 参数
1>        f:\vs2008\vc\include\utility(84) : 参见“std::operator <”的声明
1>f:\vs2008\vc\include\functional(143) : error C2676: 二进制“<”: “const a”不定义该运算符或到预定义运算符可接收的类型的转换

定位错误

定位到第一个错误行的代码位置:f:\vs2008\vc\include\functional(143) :143行代码:

		// TEMPLATE STRUCT less
template<class _Ty>
	struct less
		: public binary_function<_Ty, _Ty, bool>
	{	// functor for operator<
	bool operator()(const _Ty& _Left, const _Ty& _Right) const
		{	// apply operator< to operands
		return (_Left < _Right);
		}
	};
原因是less结构中对key对象进行了大小比较,但是我们自定义的key类型a并没有对<操作符进行重载,于是报错。

那么map容器和less有什么关系呢,我们的代码怎么回链接到这里了?

看看map的模板定义就知道了:

template<class _Kty,
	class _Ty,
	class _Pr = less<_Kty>,
	class _Alloc = allocator<pair<const _Kty, _Ty> > >
	class map
没错,申明map容器时,我们忽略了后面两个模板类,于是默认的使用了less进行比较。

关于这个_Pr详解可见:http://www.cnblogs.com/zjfdlut/archive/2011/08/12/2135698.html

解决方法

好了,知道了出错原因,我们就自己冲裁<操作符了:

bool operator<(const a& a1, const a& a2)
{
	if ( a1.m_a>=a2.m_a )
		return false;
	return true;
}
编译OK,可以使用了。

结论

因此,通过重载<操作符可以使自定义结构支持map容器。

另外的一种方法


下面介绍另一种方法,通过重写比较类函数来:

template<class T>
class Compare
{
public:
	int operator()(const T& x, const T& y)const
	{
		if ( x.m_a>=y.m_a )
			return 0;
		return 1;
	}
};

在定义map容器时,第三个模板类传入我们自己定义的类而不是用默认的:

map<a, int, Compare<a>> mp;
	a a1;
	a1.m_a		= 100;
	a1.pName	= "a1";
	a a2;
	a2.m_a		= 200;
	a2.pName	= "a2";
	mp.insert(std::make_pair(a1, 1));
	mp.insert(std::make_pair(a2, 1));
编译也OK了。至于为什么要这么做,这篇博文讲的很详细到位:http://www.cnblogs.com/zjfdlut/archive/2011/08/12/2135698.html,我就不赘余了。




C++ STL常用容器之map-multimap-unordered_map 详细介绍了STL中几种map的用法与各场景下的优缺点 阅读详情

相关推荐

MATLAB实战:手把手教你绘制发动机万有特性曲线(附完整代码)

本文提供了一份详细的MATLAB实战指南,手把手教你从发动机台架试验数据出发,通过数据预处理、核心插值算法和可视化技巧,绘制出专业、精确的发动机万有特性曲线图。文章深入解析了万有特性图的核心构成与工程意义,并附带了完整的模块化代码,帮助工程师和学生快速掌握这一关键技能。

weixin_29094539的博客 410

C++ STL: map自定义键值类型

map定义 map是STL里的一个模板类,用来存放<key, value>键值对的数据结构,它的定义如下。 template < class Key, //map::key_tpe class T, //map::mapped_type class Compare = less<Key>, .

NBA_1的博客 1576

从VBA到Python:探索CODE V API在MTF数据分析中的跨语言实践

本文详细介绍了如何从VBA转向Python,利用CODE V API实现MTF数据分析的高效工作流。通过Python的科学计算库和现代API设计,光学工程师可以大幅提升数据处理和可视化效率,实现自动化报告生成和性能优化。

weixin_29239661的博客 441

STL中map按照key和value进行排序

STL中map按照key和value进行排序 文章目录STL中map按照key和value进行排序1. STL中map按照key排序二. STL中Map的按Value排序 1. STL中map按照key排序 顺序容器有vector,list,deque 关联容器有set,map,multiset,multimap 映射(map),底层实现是红黑二叉树,相当于二分查找,复杂度O(logn) 查找—...

liuxinghai123的博客 878

量子城域网系列(六):从星型到环形,解析QKD网络拓扑的演进与选型

本文深入解析了量子密钥分发网络从星型到环形等主流拓扑结构的演进历程与核心原理。针对量子城域网的实际部署,文章详细对比了星型、总线型和环形拓扑的优缺点,并结合政务云、金融网点等典型应用场景,提供了实战选型指南,帮助读者在物理限制、安全需求与成本效率间找到最佳平衡。

weixin_29197835的博客 111

Nmap源码分析(端口扫描)

端口扫描是Nmap的核心功能,用于确定目标机的端口状态(开放、关闭、过滤等),也为Nmap的服务与版本扫描、OS扫描、脚本扫描提供基本的指引信息。所以,深入理解端口扫描的实现对分析其他的扫描方式很有帮助。 1简单回顾   首先简要回顾一下端口扫描的原理以及命令行选项。 1.1扫描原理   Nmap提供的10多种类型的端口扫描方法,如TCP SYN/ACK/FIN/Xmas/NULL/ Windows/Connect,FTP Bounce, Idle scan, UDP port u...

墨痕诉清风的博客 1596

STL(map和二维map/hdu1263)

#include #include #include using namespace std; int main() { mapm; m["a"]=1; m["b"]=2; m["c"]=3; map::iterator it; for(it=m.begin();it!=m.end();++it) co

他的博客 5214

学Simulink——十二脉波整流电路(移相变压器)谐波抵消仿真

Y:Δ = 1:√3(若 DC 同压)— 此处同相电压故 220V(Y)=220V(Δ phase)Y(相电压=220V)、Δ(线电压=380V ⇒ 相=220V,30° 移相)可经 Lbal​=0.5mH(平衡电抗)或直接短(大 L_dc 下均流尚可)✅ 直流输出纹波频率 = 12·f_line(vs 6·f_line)直流输出 → Ldc​=50mH→Cdc​=2200µF→R=30Ω。Line‑Line RMS = 380 V(⇒ 相=220V)Vdc​≈1.35⋅380≈513V(同 6‑脉波)

xiaoheshang_123的博客 58

STL——map和set

map和set

weixin_50601177的博客 603

把数据库事务边界握在手里:ABAP 里的 COMMIT CONNECTION 与 ROLLBACK CONNECTION 深度拆解

与表面是两条很短的语句,背后却牵动了连接管理、数据库 LUW、SAP LUW、隐式提交、游标生命周期、GTT 平台差异等一整片工程现实。把它们用对,你就能在不破坏主业务事务的前提下,实现跨库写入、审计落库、隔离型日志、数据集成落地等一系列“看似矛盾”的目标;用错了,它们也会悄无声息地制造一致性缺口,让问题在高峰期以 dump 或数据异常的方式爆出来。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1836

告别繁琐!VS Code 下OpenClaw零配置上手秘籍

本文介绍了在VSCode环境下零配置上手OpenClaw开发工具的最佳实践。首先详细说明了VSCode和OpenClaw插件的安装步骤,包括获取安装包、配置环境变量等准备工作。然后重点讲解了核心配置流程:设置OpenClaw路径、调整工作区参数、添加自定义代码片段等优化开发体验的方法。通过创建测试项目验证配置有效性,并针对常见的路径错误、运行报错等问题提供了排查方案。本文旨在帮助开发者快速搭建高效的OpenClaw开发环境,充分发挥VSCode与OpenClaw的组合优势,提升开发效率。无论是新手还是资深开

远程部署调试 运行安装 项目调试 二次开发 项目技术新 持续迭代 部分源码免费分享 526

map用entrySet方法做循环遍历时,不指定key-value类型可以么?

定义一个LinkedHashMap: Map<Integer, List<Integer>> listMap = new LinkedHashMap<>(); 先不指定key-value类型进行遍历: 可以发现这样取值,返回结果都是Object类型,还得进行一步转换才能匹配原先定义的类型。 指定key-value类型进行遍历: 发现这时可以直接用...

硅脂味咖啡的博客 1152

【Bug已解决】Codex CLI 报 stream disconnected before completion 解决方案

方案适用场景推荐指数更新根证书库社区验证的最常见根因⭐⭐⭐⭐⭐检查系统时间虚拟机/容器等特殊运行环境⭐⭐⭐⭐核对 base_url 配置排除证书问题后的下一步排查⭐⭐⭐⭐更换网络环境测试怀疑本地网络设备存在干扰⭐⭐⭐升级到最新版本已知版本缺陷的场景⭐⭐⭐⭐报错虽然表现形式很像网络连接问题,但社区排查的多个真实案例表明,很大一部分情况的根因其实是本机系统的 TLS 证书信任链异常或系统时间不准确,而不是单纯的网络质量问题。优先检查并更新系统根证书库,这是社区验证过的高频根因。

一键难忘的博客 8013

std::map自定义类型key

一、起始 众所周知,map是STL库中常用的关联式容器,底层实现就不多提了是平衡二叉树,今天主要关注的是map的KEY值,观看std::map源码如下: template<class _Kty, class _Ty, class _Pr = less<_Kty>, class _Alloc = allocator<pair<const _K...

三体问题 7357

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

自定义类型使用STL关联容器

上次总结STL容器时有提到,我们不能直接把自定义类型作为关联容器set或map的key。C++编译器会报错的。 如果想这样做,需要对自定义类型规定一个< 运算符。 方法1:在自定义类型内定义<运算符。 源代码示例如文章最后。需要注意以下几点。 bool operator< (const Test_Data & cmp) const 中,参数类型必须是cons...

zgcjaxj的博客 905

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

C++ STL map的自定义排序

map分别按value或key排序两种情况

zyqdxsomg 1万+

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

STL详解---set和map

在我们之前的学习中,已经了解了STL的部分容器,比如:vector,list,deque,forward_list等等,这些容器统称为序列式容器,而我们今天要将的map和set称之为关联式容器,序列式容器和关联式容器的区别就在于,序列式容器单纯为了存储数据而存在。而关联式容器不仅仅存储数据还对结构进行了存储。 在了解set和map之前,我们需要了解搜索二叉树是什么,因为set和map的底层就是一棵搜索二叉树。

分享学习的知识,记录我的技术成长道路 1700

STL中map,unordered_map的key的类型

map的key可以是struct,但是因为map底层是红黑树,是有序的,因此struct内必须重载<.unordered_map的key不能是struct. 【例1】:map #include <iostream> #include <map> using namespace std; struct stone { int a; int b; int c; i...

超级无敌小酱油的博客 2342

C++ unordered_map无法使用pair作为key的解决办法

最近在使用STL中unordered_map这种容器的时候发现无法将key设置为pair类型,编译报错信息为: error: implicit instantiation of undefined template 'std::__1::hash<std::__1::pair<int, int> > 查了下资料才发现unordered_map中没有针对pair的hash函...

骄燕的博客 6825

【C++】STL 容器 - map 关联容器 ① ( std::map 容器简介 | std::map 容器排序规则 | std::map 容器底层实现 )

一、std::map 容器 1、std::map 容器简介 2、std::map 容器排序规则 3、std::map 容器底层实现 二、代码示例 - std::map 容器 1、代码示例 2、执行结果

让 学习 成为一种 习惯 ( 韩曙亮 の 技术博客 ) 1729

C++STL之map容器

C++STL之Map容器 1 map容器的四种插入方式 非常简单,看下面代码和注释即可。这里强调一下使用下标插入,凡是写出例如m[3]而没有赋值的话都将以默认值0插入容器,key=3在容器是存在的,不能忽视。 //1 map的四种插入方法 void MapInsert(map<int, int> &m) { //1 通过模板pair对组.返回一个对组对象.其中:对组对象的模板参1为:被插入容器的(此处为map)迭代器类型;模板参2为:布尔类型,用于判断是否插入成功. std::pa

weixin_44517656的博客 566

【STL——map与multimap容器】

STL——map与multimap

努力搬砖ing~ 974

C++——STL之map容器

简单来说,std::map(C++)或者类似的 Map 结构(如 Python 中的 dict、Java 中的 HashMap),就像是一个特殊的字典。它不像数组那样用 0, 1, 2... 的数字作为下标,而是允许你用任意类型的数据作为索引来找到对应的数据。这个“索引”就是键,找到的“数据”就是值。为什么使用map容器?如果你的数据只是单纯的一排数字,用vector或数组就够了。但如果你需要通过某个特征(比如人名、ID号、配置项的名称)来快速存取数据,map就是最佳选择。语义清晰:代码里写。

2502_92691558的博客 497

STL-map/multimap容器常见错误分析

STL-map/multimap容器 一、map基本概念 简介 map中所有元素都是pair pair中第一个元素为key(键值),起到索引作用,第二个元素为value(实值) 所有元素都会根据元素的键值自动排序 map和multimap区别: map不允许容器中有重复key值元素 multimap允许容器中有重复key值元素 了解Python的同学可能知道这个和Python里的字典类型对...

wtzhu_13的博客 1443

<stl系类> map和set详解,掌握stl容器从现在开始

哈喽,小伙伴们大家好。今天我们继续来学习STL容器,今天我将主要介绍map和set的使用。话不多说,拿好小本本,我们赶快开始吧。一、关联式容器1、关联式容器概念在之前我们接触过STL的部分容器,比如vector,deque,list。这些容器统称为序列式容器,底层为线性结构,存储的是元素本身。那什么是关联式容器呢?关联式容器也是用来存储数据的,与序列式容器不同的是,关联式容器中存储的结构的键值对,有助于数据检索。...

weixin_59371851的博客 840

从一个简单的例子来看map容器使用自定义数据类型的注意事项

map和set容器和vector等一些容器有所不同,他们会按照key自动排序,这样很方便,但也出现了一个问题,如果使用自定义数据类型作为key值的话,你还不自己写一个排序方式,编译器不知道怎么排序,就会报错 比如下面的例子 #include<iostream> using namespace std; #include<map> class Person { public: Person(string name, int age) { this->m_Name = na

qpfxgg的博客 1178
上一篇: Windows消息机制详解
下一篇: LocalAlloc,VirtualAlloc,malloc,new的异同
疯狂-的-蜗牛
博客等级 码龄16年 427粉丝 104原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值