functional函数对象库学习

类模板 std::function 是一种通用多态函数包装器。std::function 的实例能存储、复制及调用任何可复制构造 (CopyConstructible) 的可调用 (Callable) 目标——函数(通过其指针)、lambda 表达式、bind 表达式或其他函数对象,以及成员函数指针和数据成员指针。

存储的可调用对象被称为 std::function目标。若 std::function 不含目标,则称它为。调用 std::function目标导致抛出 std::bad_function_call 异常。

std::function 满足可复制构造 (CopyConstructible) 和可复制赋值 (CopyAssignable) 。

成员函数

(构造函数)

构造新的 std::function 实例
(公开成员函数)

(析构函数)

析构 std::function 实例
(公开成员函数)

operator=

赋值新的目标
(公开成员函数)

swap

交换内容
(公开成员函数)

assign

(C++17 中移除)

赋值新的目标
(公开成员函数)

operator bool

检查是否包含目标
(公开成员函数)

operator()

调用其目标
(公开成员函数)
目标访问

target_type

获得所存储目标的 typeid
(公开成员函数)

target

获得指向所存储目标的指针
(公开成员函数)

示例代码

#include <functional>
#include <iostream>

struct Foo
{
	Foo(int num) : num_(num) {}
	void print_add(int i) const { std::cout << num_ + i << '\n'; }
	int num_;
};

void print_num(int i)
{
	std::cout << i << '\n';
}

struct PrintNum
{
	void operator()(int i) const
	{
		std::cout << i << '\n';
	}
};

int my_plus(int a, int b) { return a + b; }
int my_minus(int a, int b) { return a - b; }

#include <typeinfo>     // typeid

int plus_function(int a, int b) { return a + b; }
int minus_function(int a, int b) { return a - b; }

int main()
{
	// 存储自由函数
	std::function<void(int)> f_display = print_num;
	f_display(-9);

	// 存储 lambda
	std::function<void()> f_display_42 = []() { print_num(42); };
	f_display_42();

	// 存储到 std::bind 调用的结果
	std::function<void()> f_display_31337 = std::bind(print_num, 31337);
	f_display_31337();

	// 存储到成员函数的调用
	std::function<void(const Foo&, int)> f_add_display = &Foo::print_add;
	const Foo foo(314159);
	f_add_display(foo, 1);
	f_add_display(314159, 1);

	// 存储到数据成员访问器的调用
	std::function<int(Foo const&)> f_num = &Foo::num_;
	std::cout << "num_: " << f_num(foo) << '\n';

	// 存储到成员函数及对象的调用
	using std::placeholders::_1;
	std::function<void(int)> f_add_display2 = std::bind(&Foo::print_add, foo, _1);
	f_add_display2(2);

	// 存储到成员函数和对象指针的调用
	std::function<void(int)> f_add_display3 = std::bind(&Foo::print_add, &foo, _1);
	f_add_display3(3);

	// 存储到函数对象的调用
	std::function<void(int)> f_display_obj = PrintNum();
	f_display_obj(18);

	auto factorial = [](int n)
	{
		// 存储 lambda 对象以模拟“递归 lambda ”,注意额外开销
		std::function<int(int)> fac = [&](int n) { return (n < 2) ? 1 : n * fac(n - 1); };
		// 请注意 "auto fac = [&](int n){...};" 无法递归调用
		return fac(n);
	};
	for (int i{ 5 }; i != 8; ++i)
		std::cout << i << "! = " << factorial(i) << ";  ";
	std::cout << '\n';


	// function::operator= example
	std::function<int(int)> foo1, bar1;
	foo1 = std::negate<int>();                              // target
	bar1 = foo1;                                             // copy
	foo1 = std::function<int(int)>([](int x) {return x + 1; }); // move
	bar1 = nullptr;                                         // clear

	std::cout << "foo1: " << foo1(100) << '\n';

	// function::swap example
	std::function<int(int, int)> foo2, bar2;
	foo2 = std::plus<int>();
	std::cout << "foo2(10,10) is " << foo2(10, 10) << '\n';
	foo2.swap(bar2);

	//std::cout << "foo2(10,10) is " << foo2(10, 10) << '\n';
	std::cout << "bar2(20,20) is " << bar2(20, 20) << '\n';

	//function::operator bool example
	std::function<int(int, int)> foo3, bar3;
	foo3 = std::plus<int>();
	std::cout << "foo3 is " << (foo3 ? "callable" : "not callable") << '\n';
	std::cout << "bar3 is " << (bar3 ? "callable" : "not callable") << '\n';

	//function::operator() example
	// an array of functions:
	std::function<int(int, int)> fnArray[] = {
	  std::plus<int>(),
	  std::minus<int>(),
	  std::multiplies<int>()
	};

	for (auto& x : fnArray) std::cout << x(10, 5) << '\n';

	// function::target example
	std::function<int(int, int)> foo5 = my_plus;
	std::function<int(int, int)> bar5 = std::plus<int>();

	// calling using functional form:
	std::cout << foo5(100, 20) << '\n';
	std::cout << bar5(100, 20) << '\n';

	// calling by invoking target:
	std::cout << (*foo5.target<int(*)(int, int)>())(100, 20) << '\n';
	std::cout << (*bar5.target<std::plus<int>>())(100, 20) << '\n';

	// changing target directly:
	*foo5.target<int(*)(int, int)>() = &my_minus;
	std::cout << foo5(100, 20) << '\n';

	// function::target_type example
	std::function<int(int, int)> plus1 = plus_function;
	std::function<int(int, int)> plus2 = std::plus<int>();
	std::function<int(int, int)> minus1 = minus_function;
	std::function<int(int, int)> minus2 = std::minus<int>();

	std::cout << "pointers as targets:\n" << std::boolalpha;
	std::cout << "plus1 : " << (plus1.target_type() == typeid(int(*)(int, int))) << '\n';
	std::cout << "plus2 : " << (plus2.target_type() == typeid(int(*)(int, int))) << '\n';
	std::cout << "minus1: " << (minus1.target_type() == typeid(int(*)(int, int))) << '\n';
	std::cout << "minus2: " << (minus2.target_type() == typeid(int(*)(int, int))) << '\n';
	std::cout << '\n';

	std::cout << "same type?:\n";
	std::cout << "(plus1, plus2) : " << (plus1.target_type() == plus2.target_type()) << '\n';
	std::cout << "(minus1,minus2): " << (minus1.target_type() == minus2.target_type()) << '\n';
	std::cout << "(plus1, minus1): " << (plus1.target_type() == minus1.target_type()) << '\n';
	std::cout << "(plus2, minus2): " << (plus2.target_type() == minus2.target_type()) << '\n';

	return 0;
}

运行结果:

参考:

https://cplusplus.com/reference/functional/

标准库头文件 <functional> - cppreference.com
 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java进阶学习笔记31——日期时间

Date&#xff1a; 代表的是日期和时间。 分配Date对象并初始化它以表示自标准基准时间&#xff08;称为纪元&#xff09;以来的指定毫秒数&#xff0c;即1970年1月1日00:00:00。 有参构造器。 package cn.ensource.d3_time;import java.util.Date;public class Test1Date {pu…

Tomcat安装和配置(图文详解)_tomcat安装及配置教程

Tomcat是一个开源的Web应用服务器&#xff0c;它是Apache软件基金会的一个项目。Tomcat被广泛用作Java Servlet和JavaServer Pages&#xff08;JSP&#xff09;技术构建的Web应用程序的运行环境。 它是轻量级的&#xff0c;适合中小型系统和并发访问用户不是很多的场合&#x…

FPGA基于DE2-115开发板驱动HC_SR04超声波测距模块|集成蜂鸣器,led和vga提示功能

文章目录 前言一、实验原理二、Verilog文件2.1 时钟分频2.2 超声波测距2.3 超声波驱动 三、实现过程3.1 模块说明3.2 引脚分配 三、演示视频总结参考 前言 环境 硬件 DE2-115 HC-SR04超声波传感器 软件 Quartus 18.1 目标结果 使用DE2-115开发板驱动HC-SR04模块&#xff0…

力扣刷题--2085. 统计出现过一次的公共字符串【简单】

题目描述 给你两个字符串数组 words1 和 words2 &#xff0c;请你返回在两个字符串数组中 都恰好出现一次 的字符串的数目。 示例 1&#xff1a; 输入&#xff1a;words1 [“leetcode”,“is”,“amazing”,“as”,“is”], words2 [“amazing”,“leetcode”,“is”] 输出…

万字详解 MySQL MGR 高可用集群搭建

文章目录 1、MGR 前置介绍1.1、什么是 MGR1.2、MGR 优点1.3、MGR 缺点1.4、MGR 适用场景 2、MySQL MGR 搭建流程2.1、环境准备2.2、搭建流程2.2.1、配置系统环境2.2.2、安装 MySQL2.2.3、配置启动 MySQL2.2.4、修改密码、设置主从同步2.2.5、安装 MGR 插件 3、MySQL MGR 故障转…

QT之动态加载树节点(QTreeWidget)

之前写过一篇动态加载ComboBox&#xff0c;可参见下面这篇文章 QT之动态加载下拉框&#xff08;QComboBox&#xff09; 同理QTreeWidget也可以实现动态加载&#xff0c;在一些异步加载数据&#xff0c;并且数据加载比较耗时&#xff0c;非常实用。 效果 原理分析 要实现此类效…

[数据集][图像分类]骨关节炎严重程度分类数据集14038张4分类

数据集类型&#xff1a;图像分类用&#xff0c;不可用于目标检测无标注文件 数据集格式&#xff1a;仅仅包含jpg图片&#xff0c;每个类别文件夹下面存放着对应图片 图片数量(jpg文件个数)&#xff1a;14038 分类类别数&#xff1a;4 类别名称:[“grade0”,“grade2”,“grade3…

如何使用KolorPanotourPro制作全景图像网页

目录 前言 KolorPanotourPro是什么 如何制作全景网页 1.拥有全景图 2.导入图片 3.在多张全景图中跳转 4.查看制作的全景网页 结束语 前言 今天是坚持写博客的第十五天&#xff0c;继续为努力和坚持的大家点赞和鼓掌。 书接上文&#xff0c;我们讲了如何使用如何使用A…

公园【百度之星】/图论+dijkstra

公园 图论dijkstra #include<bits/stdc.h> using namespace std; typedef long long ll; typedef pair<ll,ll> pii; vector<ll> v[40005]; //a、b、c分别是小度、度度熊、终点到各个点的最短距离 ll a[40005],b[40005],c[40005],dist[40005],st[40005]; void…

1.1 OpenCV随手简记(一)

OpenCV学习篇 OpenCV (Open Source Computer Vision Library) 是一个开源的计算机视觉库&#xff0c;它提供了大量的算法和函数&#xff0c;用于图像处理、计算机视觉和机器学习等领域。 1. OpenCV 简介 1.1 OpenCV 的起源和发展 OpenCV 项目始于 1999 年&#xff0c;由 In…

IDeal下的SpringBoot项目部署

一、首先找到自己的sql文件&#xff0c;没有就从数据库挪进来 二、在Maven下打包一下&#xff08;点击package&#xff09;&#xff0c;看到BUILD SUCCESS就是打包好了 三、将上面两个文件分别挪到 linux 中对应的文件&#xff0c;没有就创建一个&#xff08;我的是spring_blog…

制作ChatPDF之Elasticsearch8.13.4搭建(一)

Elasticsearch8.x搭建 在Windows系统上本地安装Elasticsearch的详细步骤如下&#xff1a; 1. 下载Elasticsearch 访问 Elasticsearch下载页面。选择适用于Windows的版本8.13.4&#xff0c;并下载ZIP文件。 2. 解压文件 下载完成后&#xff0c;找到ZIP文件&#xff08;例如…

【2023百度之星初赛】跑步,夏日漫步,糖果促销,第五维度,公园,新材料,星际航行,蛋糕划分

目录 题目&#xff1a;跑步 思路&#xff1a; 题目&#xff1a;夏日漫步 思路&#xff1a; 题目&#xff1a;糖果促销 思路&#xff1a; 题目&#xff1a;第五维度 思路&#xff1a; 题目&#xff1a;公园 思路&#xff1a; 新材料 思路&#xff1a; 星际航行 思路…

网上蛋糕售卖店管理系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;管理员管理&#xff0c;店员管理&#xff0c;用户管理&#xff0c;商品管理&#xff0c;基础数据管理 前台账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;公告信息&#xff0c;商品…

MFC 解决Enter回车键和Esc取消键默认关闭窗口的三种方法

文章目录 问题描述问题原因解决办法方法一&#xff1a;在重载的PreTranslateMessage 函数中屏蔽回车和ESC 的消息方法二&#xff1a;重载OnOK函数方法三&#xff1a;将所有按钮类型设为普通按钮&#xff0c;并设置其中一个按钮为默认按钮 问题描述 一般情况下编写的MFC对话框程…

【如何在日志中输出精确到毫秒的时间戳】

1. 需求 在日志中输出精确到毫秒级的时间戳&#xff0c; 格式为&#xff1a;%Y-%m-%d %H:%M:%S.%MS 如&#xff1a;2024-05-30 22:33:25.821 2. 代码实现 #include <iostream> #include <chrono> #include <iomanip> #include <sstream> #include &…

锻压设备智能制造工厂物联数字孪生平台,推进制造业数字化转型

锻压设备智能制造工厂物联数字孪生平台&#xff0c;推进制造业数字化转型。随着全球制造业的飞速发展&#xff0c;数字化转型已经成为企业提升竞争力、实现可持续发展的关键。在锻压设备智能制造领域&#xff0c;工业物联数字孪生平台以其强大的数据集成、分析和管理能力&#…

k均值过程图解

k均值聚类实际上是数据空间质心的Voronoi 划分问题。

C语言 | Leetcode C语言题解之第124题二叉树中的最大路径和

题目&#xff1a; 题解&#xff1a; /*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*/ int max; int dfs(struct TreeNode* root){if(!root) return 0;int left dfs(root->left…

中继器、集线器、网桥、交换机、路由器和网关

目录 前言一、中继器、集线器1.1 中继器1.2 集线器 二、网桥、交换机2.1 网桥2.2 交换机 三、路由器、网关3.1 路由器3.2 网关 总结 前言 理解这些设备的关键是他们运行在不同的层次上。之所以存在不同层的问题&#xff0c;是因为不同的设备使用不同的信息来决定如何交换。在典…