C++ concept的概念和使用

C++ concept的概念和使用

concept 这套语法优化了模板编程,替代了原来的SFINAE编程模式,通过给模板类参数加入限制条件,使得代码可读性更强、编译更快、错误提示更容易理解。

SFINAE编程模式

SFINAE 是"Substitution Failure Is Not An Error"的简称。

模板实例化时类型推演失败不会报错,而是当成一个语言特性。利用模板通用定义和模板特化,对于不同的模板参数给予不同的实现。

int T::* 表示指向T的成员的指针。

Keywords

concept

定义类似模板的东西,在requires 中使用。

template <class T>
concept integral = std::is_integral_v<T>;

requires

有以下作用:

用于定义concept。

template <typename T>
concept ILabel = requires(T v)
{{v.buildHtml()} -> std::convertible_to<std::string>;
};

用于为模板施加限制。

template <typename T>
requires CONDITION
void DoSomething(T param) { }

另一种写法

template <typename T>
void DoSomething(T param) requires CONDITION
{ 
}

代码示例

我自己的例子

template <typename T>
concept should_be_float = std::is_floating_point_v<T>;template <typename T> requires should_be_float<T>
T add(T a, T b) { return a + b; }void concept_test()
{auto r = add(1.2, 3.3);auto r2 = add(1, 2);  // 编译不过
}

STL的例子

template <class _LTy, class _RTy>
concept assignable_from = is_lvalue_reference_v<_LTy>&& common_reference_with<const remove_reference_t<_LTy>&, const remove_reference_t<_RTy>&>&& requires(_LTy _Left, _RTy&& _Right) {{ _Left = static_cast<_RTy&&>(_Right) } -> same_as<_LTy>;};

concepts library

<concepts>头文件中定义了一些预定义的concept。

  • same_as

  • derived_from

  • convertible_to

  • common_reference_with

  • common_with

  • integral

  • signed_integral

  • unsigned_integral

  • floating_point

  • assignable_from

  • swappable / swappable_with

  • destructible

  • constructible_from

  • default_initializable

  • move_constructible

  • copy_constructible

  • boolean-testable

  • equality_comparable

  • movable

  • copyable

  • semiregulasr

  • regular

  • invocable

  • predicate

  • relation

  • equivalence_relation

  • strict_weak_order

语法糖

auto 关键字

省去template,将

template <typename T>
auto foo(T p) {}

改写为:

auto foo(auto p) {} 

可以极为化简模板函数代码,比如:

auto foo2(auto a, auto b)
{return a + b;
}int main()
{std::cout << foo2(1.2, 2) << std::endl;std::cout << foo2(1, 2) << std::endl;std::cout << foo2(1.2, 1.6) << std::endl;
}

与concepts合用

void print3(const std::ranges::range auto& c)
{for (auto && elem : c){std::cout << elem << ", ";}std::cout << std::endl;
}
int main()
{std::vector<int> c{ 1,2,4,5,12,23,88,23, 17 };print3(c);
}

template + concept 更加可读的写法

用concept名字替代关键字 template 或者 class

template <std::integral T>
auto sum(const std::vedctor<T>& vec)
{// return ...
}

还可以跟模板可变参数合用。

template <typename T>
concept number = std::integral<T> || std::floating_point<T>;template <number ...TArgs>
auto sum_all(TArgs ...args)
{return (... + args);
}int main()
{std::cout << sum_all(1, 2, 3) << std::endl;std::cout << sum_all(1, 2.2, 3) << std::endl;std::cout << sum_all(1.1, 2.2, 3.3) << std::endl;
}

结合auto关键字,能有更简洁的写法。

template <typename T>
concept number = std::integral<T> || std::floating_point<T>;auto sum_all(const number auto & ...args)
{return (... + args);
}int main()
{std::cout << sum_all(1, 2, 3) << std::endl;std::cout << sum_all(1, 2.2, 3) << std::endl;std::cout << sum_all(1.1, 2.2, 3.3) << std::endl;
}

鸭子类型

利用concepts语言特性,得到类似Ruby语言那样的鸭子类型(duck typing)和mixin特性(例如Ruby的Enumerable)。

鸭子类型是指“如果一个动物走起来像鸭子,叫起来也像鸭子,那么它就是鸭子”。也就是说不关心一个类型是不是继承于某个基类,而是看类型是否实现了某些方法(在concepts中可以扩展成某些成员变量、成员类型、返回特定类型的方法等等)。基于鸭子类型实现了mixin,mixin是指非侵入式地为某个鸭子类型的所有类型赋予某方面的能力。例如Ruby的Enumerable对所有实现了“取值”和“下一个”的方法的类型,提供了一系列迭代器相关的方法(first, last, find 等等)。鸭子类型的好处是在于其“非侵入式”。

用concept定义一个鸭子类型。

template <typename T>
concept IClock = requires(T c) {c.start();c.stop();c.getTime();
};void foo3(IClock auto& clock)
{clock.start();clock.stop();
}

其他

尾部返回类型

引入尾部返回类型的背后原因是模板函数根据模板参数确定返回类型。

template<typename A, typename B>
??? multiply(A a, B b) { return a*b}

C++编译器是从左往右处理代码(就是lexical order),当扫描到返回类型的时候尚未扫描到模板参数a和b,因此无法使用decltype(a*b)这个东西。Trailing Return Types解决这个问题的方法如下代码所示:

template<typename A, typename B>
auto multiply(A a, B b) -> decltype(a*b) { return a * b; }

其他原因是:

  1. 跟lambda定义的风格一样;
  2. 名字比返回类型重要,应该在前面;
  3. 与数学上函数定义(R -> R)一致。

References

  1. [C++ Trailing Return Types ‐ Daniel Sieger](https://www.danielsieger.com/blog/2022/01/28/cpp-trailing-return-types.html#:~:text=Trailing return types are an alternative syntax introduced,return type after the function name and parameters%3A)
  2. C++20 Concepts - a Quick Introduction - C++ Stories (cppstories.com)
  3. Concepts library (since C++20) - cppreference.com
  4. Predefined C++20 Concepts: Callables - C++ Stories (cppstories.com)
  5. Requires-expression | Andrzej’s C++ blog (wordpress.com)

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

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

相关文章

msql 批量更新生成不同的uuid()

有时需要对表里的批量数据设置主键uuid&#xff0c;要求每条数据的uuid都不一样。 一、方法&#xff1a; UPDATE honghang_1month_list SET idUUID();UPDATE honghang_1month_list SET idREPLACE(id, -, );注意不能直接执行UPDATE honghang_1month_list SET idREPLACE(UUID()…

Amazon Aurora MySQL 和 Amazon RDS for MySQL 集群故障转移和只读实例扩容时间测试

01 测试背景 Amazon Aurora MySQL 是与 MySQL 兼容的关系数据库&#xff0c;专为云而打造&#xff0c;性能和可用性与商用数据库相当&#xff0c;成本只有其 1/10。 Amazon RDS for MySQL 让您能够在云中更轻松设置、操作和扩展 MySQL 部署。借助 Amazon RDS&#xff0c;您可以…

Android 13.0 Launcher3定制之双层改单层(去掉抽屉式二)

1.概述 在13.0的系统产品开发中,对于在Launcher3中的抽屉模式也就是双层模式,在系统原生的Launcher3中就是双层抽屉模式的, 但是在通过抽屉上滑的模式拉出app列表页,但是在一些产品开发中,对于单层模式的Launcher3的产品模式也是常用的功能, 所以需要了解抽屉模式,然后修…

CSS笔记(黑马程序员pink老师前端)CSS初始化

京东首页CSS初始化 <style>/* 清除默认的padding和margin *//* 通配符选择器渲染较慢&#xff0c;一般用标签选择器 */* {margin: 0;padding: 0;/* CSS3盒子模型 */box-sizing:border-box;}/* em和i中的文字不再倾斜 */em,i {font-style: normal}/* 去除列表前的圆点样式…

SpringBoot环境MongoDB分页+去重+获取去重后的原始数据

最近有个比较复杂的MongoDB查询需求&#xff0c; 要求1&#xff1a;获取最近订单表中的请求参数信息&#xff0c;并需要按照请求参数中的账号进行去重 要求2&#xff1a;数据量可能比较大&#xff0c;因此需要做分页查询 研究了大半天&#xff0c;终于搞出了解决方案&#xff0…

ubuntu系统安装hadoop

Hadoop 分布式计算平台&#xff0c;核心是分布式文件系统HDFS ubantu下 安装jdk wget https://repo.huaweicloud.com/openjdk/18.0.1.1/openjdk-18.0.1.1_linux-aarch64_bin.tar.gz tar -zxvf openjdk-18.0.1.1_linux-aarch64_bin.tar.gz mv jdk-18.0.1.1/ /usr/java18 ech…

【Spring Bean的生命周期实现方式】

文章目录 Spring Bean的生命周期实现方式实例化属性赋值初始化销毁Spring Bean的生命周期实现方式 Spring Bean的生命周期决定了一个Bean的整个生命周期,它分为四个阶段:实例化、属性赋值、初始化和销毁。 实例化 实例化通过构造器实例化和工厂方法实例化两种方式实现;构…

python项目打包上传PyPI

PyPI PyPI&#xff08;Python Package Index&#xff09;是Python编程语言中最大的第三方软件包仓库&#xff0c;它是Python生态系统的核心组成部分。PyPI提供了一个集中存储和分发Python软件包的平台&#xff0c;为开发者和用户提供了便利的方式来查找、安装和分享各种Python…

MySQL触发器详解保证入土

文章目录 简介一、MySQL触发器基础触发器分类基础常用关键字1. 定义触发器2. 创建和删除触发器3. 执行时机和条件 二、MySQL触发器的使用场景1. 数据完整性约束插入触发器更新触发器删除触发器 2. 数据变更日志的记录与追踪3. 触发器与存储过程的对比与选择 三、触发器的性能和…

C++学习笔记(重载、类)

C 1、函数重载2、类2.1、类的方法和属性2.2、类的方法的定义2.3、构造器和析构器2.4、基类与子类2.5、类的public、protected、private继承2.6、类的方法的重载2.7、子类方法的覆盖2.8、继承中的构造函数和析构函数 1、函数重载 函数重载大概可以理解为&#xff0c;定义两个名…

【2023年数学建模国赛】C题解题思路

第一问 要求分析分析蔬菜各品类及单品销售量的分布规律及相互关系。该问题可以拆分成三个角度进行剖析。 1&#xff09;各种类蔬菜的销售量分布、蔬菜种类与销售量之间的关系&#xff1b;2&#xff09;各种类蔬菜的销售量的月份分布、各种类蔬菜销售量与月份之间的相关关系&a…

Curator实现Zookeeper分布式锁

Curator实现Zookeeper分布式锁 1、介绍 Curator是netflix公司开源的一套zookeeper客户端&#xff0c;目前是Apache的顶级项目。与Zookeeper提供的原生客户端相比&#xff0c;Curator的抽象层次更高&#xff0c;简化了Zookeeper客户端的开发量。Curator解决了很多zookeeper客户…

C语言实现三字棋

实现以下&#xff1a; 1游戏不退出&#xff0c;继续玩下一把&#xff08;循环&#xff09; 2应用多文件的形式完成 test.c. --测试游戏 game.c -游戏函数的实现 game.h -游戏函数的声明 (2)游戏再走的过程中要进行数据的存储&#xff0c;可以使用3*3的二维数组 char bor…

idea VCS配置多个远程仓库

Idea VCS配置多个远程仓库 首先要有两个或多个不同远程仓库地址 idea 添加数据源 查看推送记录 添加数据源 ok之后填写账号密码 推送本地项目 选择不同远程地址 push 查看不同远程地址的 不同分支的 推送记录 不期而遇的温柔&#xff1a; 应用开源架构进行项目开发&#xff0…

Java版企业电子招标采购系统源码—企业战略布局下的采购寻源

功能模块&#xff1a; 待办消息&#xff0c;招标公告&#xff0c;中标公告&#xff0c;信息发布 描述&#xff1a; 全过程数字化采购管理&#xff0c;打造从供应商管理到采购招投标、采购合同、采购执行的全过程数字化管理。通供应商门户具备内外协同的能力&#xff0c;为外部供…

Qt串口基本设置与协议收发

前言 1.一直都想要做一个Qt上位机&#xff0c;趁着这个周末有时间&#xff0c;动手写一下 2.comboBox没有点击的信号&#xff0c;所以做了一个触发的功能 3.Qt的数据类型很奇怪&#xff0c;转来转去的我也搞得很迷糊 4.给自己挖个坑&#xff0c;下一期做一个查看波形的上位…

Android 9.0 网络之netd详解

一、DHCP流程 分析netd之前先了解一下网络自动获取IP流程&#xff0c;借鉴下图流程查看代码&#xff1a; &#xff08;1&#xff09;WIFI扫描到可用网络后进行连接&#xff0c;代码路径&#xff1a;\frameworks\opt\net\wifi\service\java\com\android\server\wifi\WifiStateMa…

OJ练习第167题——单词接龙

单词接龙 力扣链接&#xff1a;127. 单词接龙 题目描述 字典 wordList 中从单词 beginWord 和 endWord 的 转换序列 是一个按下述规格形成的序列 beginWord -> s1 -> s2 -> … -> sk&#xff1a; 每一对相邻的单词只差一个字母。 对于 1 < i < k 时&…

Vue2+Vue3笔记(尚硅谷张天禹老师)day03

声明:只是记录&#xff0c;初心是为了让页面更好看,会有错误,我并不是一个会记录的人&#xff0c;所以有点杂乱无章的感觉&#xff0c;我先花点时间把视频迅速过掉&#xff0c;再来整理这些杂乱无章的内容 计划是一天更新一点 待做的东西 完成博客记录把完成后的博客记录拆成单…

计算机网络的故事——简单的HTTP协议

简单的HTTP协议 文章目录 简单的HTTP协议一、简单的HTTP协议 一、简单的HTTP协议 HTTP是不保存状态的协议&#xff0c;为了实现保存状态功能于是引入了Cookie技术。 method: get:获取资源 post:传输实体主体 put:传输文件 head:获取报文首部&#xff0c;用于确认URI的有效性以…