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,一经查实,立即删除!

相关文章

k8s 部署 nexus3 详解

创建命名空间 nexus3-namespace.yaml apiVersion: v1 kind: Namespace metadata:name: nexus-ns创建pv&pvc nexus3-pv-pvc.yaml apiVersion: v1 kind: PersistentVolume metadata:name: nfs-pvnamespace: nexus-ns spec:capacity:storage: 3GiaccessModes:- ReadWriteM…

Redis的6.0以上为啥又支持多线程

Redis 在 6.0 版本之前一直采用单线程架构&#xff0c;这是因为 Redis 主要是内存操作&#xff0c;单线程模型足以应对大部分高性能场景。而单线程模型的优势在于避免了多线程带来的上下文切换和锁的开销&#xff0c;使得 Redis 保持极高的性能和简单性。 然而&#xff0c;随着…

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…

Java基础15-Java高级(单元测试、反射、注解、动态代理)

十五、Java高级 单元测试、反射、注解、动态代理。 1、单元测试 定义&#xff1a;就是针对最小的功能单元(方法),编写测试代码对其进行正确性测试。 1.1 Junit单元测试框架 可以用来对方 法进行测试&#xff0c;它是第三方公司开源出来的(很多开发工具已经集成了Junit框架&…

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、…

分布式存储架构 与分布式一致性协议

分布式存储架构可以分为无中心节点架构和有中心节点架构。它们的设计在系统中的角色分配、数据管理、协调方式等方面有所不同。 1. 无中心节点架构&#xff08;Decentralized/Peer-to-Peer Architecture&#xff09; 在无中心节点的分布式存储架构中&#xff0c;所有节点都是…

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表达式的使用】…

一些有趣的整人小病毒

windows的小病毒 第一个占用资源&#xff08;最简单的病毒&#xff09; 打开一个文本文件&#xff0c;输入%0|%0&#xff0c;然后就命名为xxx.bat&#xff0c;就可以把你的电脑CPU利用率大大地提高然后只能重启了 第二个无限弹出窗口&#xff08;也很简单&#xff09; 打开…