news 2026/9/5 20:12:43

【C++】Pair实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【C++】Pair实现

C++20 Pair 实现详解

代码概览

这是一个模仿std::pair的现代 C++20 实现,使用了 concepts、完美转发等特性。

关键点

1. 默认成员初始化器

T1 first{};T2 second{};

为什么用{}

写法Pair<int, int> p;的结果
T1 first;first是垃圾值
T1 first{};first0

{}确保值初始化,基本类型会被初始化为零。

2. 默认构造函数的约束

constexprPair()requires(std::default_initializable<T1>&&std::default_initializable<T2>)=default;

作用:只有当T1T2都可以默认构造时,Pair才能默认构造。

structNoDefault{NoDefault(int){}// 没有默认构造函数};Pair<NoDefault,int>p1;// 编译错误,清晰的错误信息Pair<NoDefault,int>p2(NoDefault(1),2);// OK

3. 转发构造函数

template<typenameU1,typenameU2>constexprPair(U1&&x,U2&&y):first(std::forward<U1>(x)),second(std::forward<U2>(y)){}

关键概念:万能引用 vs 右值引用

template<typenameT>voidfoo(T&&x);// T 在此处推导 → 万能引用template<typenameT>structBar{voidbaz(T&&x);// T 已经固定 → 右值引用};

为什么用std::forward

Pair<Counter,Counter>p1(c,c);// c 是左值 → 拷贝Pair<Counter,Counter>p2(std::move(c),Counter(10));// 右值 → 移动

std::forward保持参数的值类别(左值/右值)。

4. 转换构造函数的约束

template<typenameU1,typenameU2>requires(!std::same_as<Pair<U1,U2>,Pair<T1,T2>>)constexprPair(constPair<U1,U2>&other)

为什么需要这个约束?

防止与拷贝构造函数冲突:

Pair<int,int>p1(1,2);Pair<int,int>p2(p1);// 应该调用拷贝构造函数,不是转换构造函数

如果没有约束,两个构造函数都匹配,可能导致歧义。

5.= default的含义

Pair(constPair&)=default;

意思:让编译器生成默认实现。

注意:= default不等于 “初始化所有成员为零”,而是 “做编译器默认会做的事”。

structS{intx;S()=default;};S s1;// x 是垃圾值(默认初始化)S s2{};// x 是 0(值初始化)

6.make_pair使用std::decay_t

template<typenameT1,typenameT2>constexprPair<std::decay_t<T1>,std::decay_t<T2>>make_pair(T1&&x,T2&&y)

为什么?

输入类型std::decay_t结果
int&int
const int&int
int[10]int*
int(double)int(*)(double)

避免存储引用或数组类型:

inta=1;autop=make_pair(a,2);// Pair<int, int>,不是 Pair<int&, int>

7. Swap 的 ADL 技巧

voidswap(Pair&other)noexcept{usingstd::swap;// 引入 std::swap 作为后备swap(first,other.first);// ADL 会找到更好的重载swap(second,other.second);}

如果T1有自定义的swap,会优先使用它。

总结表

构造函数用途关键点
Pair()默认构造需要约束default_initializable
Pair(U1&&, U2&&)从任意值构造完美转发
Pair(const Pair&)拷贝= default
Pair(Pair&&)移动= default
Pair(const Pair<U1,U2>&)转换拷贝需要排除相同类型
Pair(Pair<U1,U2>&&)转换移动需要排除相同类型
#include<concepts>#include<type_traits>#include<utility>template<typenameT1,typenameT2>structPair{T1 first{};T2 second{};// ConstructorsconstexprPair()requires(std::default_initializable<T1>&&std::default_initializable<T2>)=default;// Defaulttemplate<typenameU1,typenameU2>constexprPair(U1&&x,U2&&y):first(std::forward<U1>(x)),second(std::forward<U2>(y)){}// ForwardingPair(constPair&)=default;// CopyPair(Pair&&)=default;// Movetemplate<typenameU1,typenameU2>requires(!std::same_as<Pair<U1,U2>,Pair<T1,T2>>)constexprPair(constPair<U1,U2>&other):first(other.first),second(other.second){}// Converting copytemplate<typenameU1,typenameU2>requires(!std::same_as<Pair<U1,U2>,Pair<T1,T2>>)constexprPair(Pair<U1,U2>&&other):first(std::move(other.first)),second(std::move(other.second)){}// Converting move// AssignmentPair&operator=(constPair&other)=default;Pair&operator=(Pair&&other)noexcept=default;template<typenameU1,typenameU2>requires(!std::same_as<Pair<U1,U2>,Pair<T1,T2>>)Pair&operator=(constPair<U1,U2>&other){first=other.first;second=other.second;return*this;}template<typenameU1,typenameU2>requires(!std::same_as<Pair<U1,U2>,Pair<T1,T2>>)Pair&operator=(Pair<U1,U2>&&other){first=std::move(other.first);second=std::move(other.second);return*this;}// Swapvoidswap(Pair&other)noexcept{usingstd::swap;swap(first,other.first);swap(second,other.second);}// Comparison (C++20)booloperator==(constPair&other)const=default;autooperator<=>(constPair&other)const=default;};// Helper functionstemplate<typenameT1,typenameT2>constexprPair<std::decay_t<T1>,std::decay_t<T2>>make_pair(T1&&x,T2&&y){returnPair<std::decay_t<T1>,std::decay_t<T2>>(std::forward<T1>(x),std::forward<T2>(y));}template<typenameT1,typenameT2>voidswap(Pair<T1,T2>&a,Pair<T1,T2>&b)noexcept{a.swap(b);}
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/4 10:34:39

深度剖析Proteus元器件库大全的查找方法

如何在Proteus中高效查找元器件&#xff1f;一文掌握精准检索与库管理实战技巧你有没有遇到过这种情况&#xff1a;打开Proteus准备画个电路&#xff0c;想找个常见的DS18B20温度传感器&#xff0c;结果在“Pick Device”里翻了半天没找到&#xff1b;或者输入“stm32”跳出来几…

作者头像 李华
网站建设 2026/9/3 2:03:18

UltraISO注册码最新版不香了?看看ms-swift如何改变开发者生态

ms-swift如何重塑大模型开发新范式 在AI技术飞速演进的今天&#xff0c;我们正经历一场从“模型创新”到“工程落地”的深刻转型。过去几年&#xff0c;大模型的研究重心集中在架构突破与参数规模扩张上——Llama、Qwen、Mistral等不断刷新性能边界。然而&#xff0c;当企业试图…

作者头像 李华
网站建设 2026/9/3 3:49:35

图解说明I2C时序在工控EEPROM操作中的精准控制

工控现场的I2C通信为何总“抽风”&#xff1f;一张波形图说清EEPROM读写背后的时序真相你有没有遇到过这样的场景&#xff1a;设备在实验室跑得好好的&#xff0c;一到工厂现场就频繁出现参数丢失、校准失效&#xff0c;甚至I2C总线直接锁死&#xff0c;MCU像卡住一样动弹不得&…

作者头像 李华
网站建设 2026/9/5 4:04:00

FeedMe:3步教你打造专属AI智能信息聚合平台

FeedMe&#xff1a;3步教你打造专属AI智能信息聚合平台 【免费下载链接】feedme 实时聚合 Hacker News/Github Trending/Higging Face Daily Papers 等平台信息&#xff0c;AI 生成中文摘要 项目地址: https://gitcode.com/gh_mirrors/feedme1/feedme 在信息过载的时代&…

作者头像 李华
网站建设 2026/9/3 19:06:26

VeighNa量化交易框架终极指南:从零构建专业交易系统

VeighNa量化交易框架终极指南&#xff1a;从零构建专业交易系统 【免费下载链接】vnpy 基于Python的开源量化交易平台开发框架 项目地址: https://gitcode.com/vnpy/vnpy 你是否想要构建一个稳定可靠的量化交易系统&#xff0c;却苦于技术门槛过高&#xff1f;面对复杂的…

作者头像 李华