C++ 20 Concept

    concept主要用来定义模板参数的约束,最明显的作用就是在模板参数不满足类型的约束时编译器不再给出几千行奇奇怪怪的错误。当然还有其它的作用,比如说concepts可以用来实现函数的重载、新的concepts可以基于已有的concepts定义从而进行扩展等等下面以实现通用参数类型转换器来展示concept的使用方法。假设输入类型 IN, 输出类型 OUT,针对不同的场景,来进行不同的实现
  •       1、IN、OUT一致, 可以直接输出
    
  •       2、可以通过std::stringstream来进行输入、输出进行转换的 
    
  •       3、复杂容器类型
    

    1、 判断IN、OUT是否一致

template<typename IN, typename OUT>
concept is_same_type =  std::is_same<IN, OUT>::value;

2、判断是否可以进行范围操作

template <typename BEG, class END>
concept item_range = requires(BEG bg, END ed) {{ ++bg };{ *bg };requires !std::is_void_v<decltype(*bg)>;{ bg != ed };
};template <typename T>
concept iter_able = std::is_array_v<T>|| requires(T value) {{ value.begin() };{ value.end() };requires item_range<decltype(value.begin()), decltype(value.end())>;}|| requires(T value) {{ std::begin(value) };{ std::end(value) };requires item_range<decltype(std::begin(value)), decltype(std::end(value))>;};

3、判断是否可以进程insert操作的容器

template<typename T>
concept is_container = requires(T res, T::value_type v) {res.insert(res.begin(), v);
};

4、判断是否符合pair的容器

template<typename T>
concept is_pair_container = requires(T res, T::value_type v) {res.emplace(v);v.first;v.second;
};

转换器代码

#include <sstream>
#include <string>
#include <iostream>
#include <map>
#include <vector>
#include <list>
#include <concepts>//参数转换类
template<typename OUT>
class Convert
{
public://输入、输出类型一致template<typename IN>requires is_same_type<IN, OUT>Convert(const IN& val):m_value(val){}template<typename IN>requires (!is_same_type<IN, OUT> &&  !(iter_able<IN> &&  iter_able<OUT>))Convert(const IN& val){std::stringstream ss;ss << val;//向流中传值ss >> m_value;//向result中写入值}Convert(const char* val){std::stringstream ss;ss << val;//向流中传值ss >> m_value;//向result中写入值}//容器类转换辅助函数template<typename IN>requires (is_container<OUT> && !is_pair_container<OUT>)void ConvertHelper(const IN& val){m_value.insert(m_value.end(), Convert<typename OUT::value_type>(val)());}template<typename IN>requires (!is_container<OUT>)void ConvertHelper(const IN& val){throw "无效容器";}template<typename IK, typename IV>requires is_pair_container<OUT>void ConvertHelper(const std::pair<IK, IV>& val){m_value.emplace(Convert<typename std::decay<typename OUT::value_type::first_type>::type>(val.first)(), Convert<typename std::decay<typename OUT::value_type::second_type>::type>(val.second)());}template<typename IK, typename IV>requires (!is_pair_container<OUT>)void ConvertHelper(const std::pair<IK, IV>& val){throw "pair 类型只支持同类型容器转换";}//容器转换template<typename IN>	requires (!is_same_type<IN, OUT> && iter_able<IN> && iter_able<OUT> )Convert(const IN& val){for (auto & v : val){ConvertHelper(v);}}OUT operator()(){return m_value;}
public:OUT m_value; 
};//特化
template<>
class Convert<const char*>
{
public://输入、输出类型一致template<typename IN>Convert(const IN& val){std::stringstream ss;ss << val;//向流中传值m_value = ss.str();}const char* operator()(){return m_value.c_str();}
public:std::string m_value; 
};

转换测试


int main(int argc, char* argv[])
{//常用类型转换std::cout <<  Convert<int>(234)() << std::endl;std::cout <<  Convert<int>(std::string("234"))() << std::endl;std::cout <<  Convert<std::string>("456")() << std::endl;std::cout <<  Convert<double>("456.12")() << std::endl;std::cout <<  Convert<const char*>("456.12")() << std::endl;//容器类型转换std::vector<std::string> val = {"123", "345", "345"};auto cValue  = Convert<std::vector<int>>(val)();for(auto item : cValue){std::cout <<  item << std::endl;}//数组向容器转换int a[] = {1,2,3,4,5};auto ca = Convert<std::vector<int>>(a)();for(auto item : ca){std::cout <<  item << std::endl;}//支持pair的容器转换std::map<std::string, std::string> mval  = {{"123", "1"}, {"234", "3"}};auto cmval = Convert<std::map<int, int>>(mval)();for(auto item : cmval){std::cout <<  item.first << ":" << item.second << std::endl;}return 0;
}

总结: 实际应用中,各种类型的转换可能复杂的多,但通过实现不难发现,通过concept来定义模板参数的约束, 可以大大简化模板参数类型的萃取工作。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/57530.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++:模板的特化与分离编译

之前我们在介绍模板的时候仅仅是简单的介绍了模板的用法&#xff0c;本篇文章我们来详细的介绍下模板中比较重要的几个点。 一&#xff0c;非类型模板参数 我们之前的c中&#xff0c;会将经常使用的而又确保在我们程序的运行过程中值不会改变的值进行#define&#xff1a; #d…

初入编程之路,启航代码海

#1024程序员节|征文# 前言 今天又是1024程序员节了&#xff0c;第一次听说这个节日是在我在23年刚刚上大一的时候听学长他们说的&#xff0c;如今已经是24年了&#xff0c;虽然只学习了一年的编程但我已经了解到了这条路上的不易。希望能够在这条路上面一路坚持下去&#xff0…

力扣_斐波那契数列

本题目本质和爬楼梯是一样的&#xff0c;主要运用的是递归来解题。 class Solution:my_dict {}def fib(self, n: int) -> int:if self.my_dict.get(n) is not None: # 先判断有没有计算过这个值return self.my_dict.get(n)tempResult 0if n > 2:tempResult self.fib…

075_基于springboot的万里学院摄影社团管理系统

目录 系统展示 开发背景 代码实现 项目案例 获取源码 博主介绍&#xff1a;CodeMentor毕业设计领航者、全网关注者30W群落&#xff0c;InfoQ特邀专栏作家、技术博客领航者、InfoQ新星培育计划导师、Web开发领域杰出贡献者&#xff0c;博客领航之星、开发者头条/腾讯云/AW…

MySql中使用findInSet和collection实践

FIND_IN_SET 需求如下&#xff1a;有张用户表&#xff0c;表里有个字段叫school&#xff0c;意为这个用户上过哪些学校&#xff0c;数据库里存的就是字符串类型&#xff0c;存的值类似"2,5,12"&#xff0c;要求就是查询出上过id为2的学校有哪些用户 解决方法&#x…

【JAVA毕设】基于JAVA的酒店管理系统

一、项目介绍 本系统前端框架采用了比较流行的渐进式JavaScript框架Vue.js。使用Vue-Router实现动态路由&#xff0c;Ajax实现前后端通信&#xff0c;Element-plus组件库使页面快速成型。后端部分&#xff1a;采用SpringBoot作为开发框架&#xff0c;同时集成MyBatis、Redis、…

qt生成uuid,转成int。ai回答亲测可以

// 生成一个随机的UUID QUuid uuid QUuid::createUuid(); // 将UUID转换为字符串 QString uuidStr uuid.toString(QUuid::WithoutBraces);// 计算MD5哈希值 QByteArray hash QCryptographicHash::hash(uuidStr.toUtf8(), QCryptographicHash::Md5);// 提取前8个字节并转换为…

云曦10月13日awd复现

一、防御 1、改用户密码 passwd <user> 2、改数据库密码 进入数据库 mysql -uroot -proot 改密码 update mysql.user set passwordpassword(新密码) where userroot; 查看用户信息密码 select host,user,password from mysql.user; 改配置文件&#xff0c;将密码改为自己…

电脑技巧:Rufus——最佳USB启动盘制作工具指南

目录 一、功能强大&#xff0c;兼容性广泛 二、界面友好&#xff0c;操作简便 三、快速高效&#xff0c;高度可定制 四、安全可靠&#xff0c;社区活跃 在日常的电脑使用中&#xff0c;无论是为了安装操作系统、修复系统故障还是进行其他需要可引导媒体的任务&#xff0c;拥…

使用 Python结合随机User-Agent与代理池进行网络请求

1. 引言 在爬虫开发过程中&#xff0c;为了模拟真实的用户行为&#xff0c;避免被目标网站识别并封锁&#xff0c;通常需要使用随机的User-Agent以及代理IP来发送网络请求。本文将介绍如何通过Python实现这一功能&#xff0c;包括设置随机User-Agent、读取代理列表&#xff0c…

web网页

HTML代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>wyy</title><!-- 引…

VSCODE c++不能自动补全的问题

最近安装了vscode&#xff0c;配置了C/C扩展&#xff0c;也按照网上说的配置了头文件路径 我发现有部分头文件是没办法解析的&#xff0c;只要包含这些头文件中的一个或者多个&#xff0c;就没有代码高亮和代码自动补全了&#xff0c;确定路径配置是没问题的&#xff0c;因为鼠…

Linux笔记之文件查找和搜索命令which,find,locate,whereis总结

Linux笔记之文件查找和搜索命令which,find,locate,whereis总结 code review! 文章目录 Linux笔记之文件查找和搜索命令which,find,locate,whereis总结1.对比2.whereis 和 which 命令区别3.locate 和 find 命令区别 1.对比 命令功能说明备注which常用于查找可直接执行的命令。…

基于ssm的萌宠商城管理系统【附源码】

基于ssm的萌宠宜家商城系统&#xff08;源码L文说明文档&#xff09; 目录 4 系统设计 4.1 系统概述 4.2 系统概要设计 4.3 系统功能结构设计 4.4 数据库设计 4.4.1 数据库E-R图设计 4.4.2 数据库表结构设计 5 系统实现 5.1 管理员功能介绍 …

【C++中的lambda表达式】

不需要借口&#xff0c;爱淡了就放手....................................................................................................... 文章目录 前言 一、【lambda表达式介绍】 1、【lamda表达式的概念】 2、【lamda表达式的语法】 二、【lambda表达式的使用】…

CAS简介

#1024程序员节&#xff5c;征文# CAS是什么&#xff1f; CAS&#xff08;Compare And Swap&#xff09;&#xff0c;即比较与交换&#xff0c;是一种乐观锁的实现方式&#xff0c;用于在不使用锁的情况下实现多线程之间的变量同步。 CAS操作包含三个操作数&#xff1a;内存位…

Stability.AI 发布 SD3.5 模型,能否逆袭击败 FLUX?如何在ComfyUI中的使用SD3.5?

就在前天&#xff0c;Stability AI 正式发布了 Stable Diffusion 3.5版本&#xff0c;包括 3 款强大的模型&#xff1a; Stable Diffusion 3.5 Large&#xff1a;拥有 80 亿参数&#xff0c;提供卓越的图像质量和精确的提示词响应&#xff0c;非常适合在 1 兆像素分辨率下的专…

鸿蒙开发:走进stateStyles多态样式

前言 一个组件&#xff0c;多种状态下&#xff0c;我们如何实现呢&#xff1f;举一个很简单的案例&#xff0c;一个按钮&#xff0c;默认状态下是黑色背景&#xff0c;点击后是红色&#xff0c;手指放开后还原黑色。 我们自然而然的就会想到利用手势的按下和抬起&#xff0c;…

美课+, 一个公司老项目,一段程序猿的技术回忆

前言 "美课"项目从2018年3月26号开始启动到2018年6月8号结束,总计两个月多的时间,项目的时间节点比较紧张.虽然最后没有上线很遗憾,但是,不管是在流程和项目上,对自己都是一次不错的尝试.下面我就对这次项目做一下iOS端的整体总结. #### 技术难点 *** 在iOS端,我感到…

鸿蒙应用开发:数据持久化

最近在搞公司项目用到了鸿蒙端的数据持久化&#xff0c;特来跟大家分享一下。 在鸿蒙开发中&#xff0c;可以使用以下几个包来实现数据的持久化处理&#xff1a; Data Ability 通过数据能力组件&#xff0c;开发者可以实现复杂的数据操作&#xff0c;包括增、删、改、查等功…