C++ 学习系列 -- std::function 与 std::bind

一  std::function  与 std::bind 的介绍

     1. std::function  

     std::function 是 c++ 11 的新特性 ,包含在头文件<functional>中,为了更方便的调用函数而引入。

       std::function 是一个函数包装器(function wrapper),可以包装任何可调用实体,包括如下几种:

       普通函数、函数指针、成员函数、静态函数、lambda 表达式 与 仿函数对象。

     std::function 对象实例可以拷贝与移动,可以使用指定的调用特征来调用目标元素。当 std::function 对象实例未包含任何实体时,调用该 std::function 对象实例时,会抛出std::bad_function_call异常。

    2. std::bind

      std::bind 是 c++ 11 的新特性,其作用与其字面名称相似,是为了绑定函数的某些参数。

std::bind 是一种延迟计算的思想,将可调用函数对象保存起来,在需要调用时再去调用。可以绑定

仿函数对象、普通函数与成员函数,其参数可以支持占位符。

占位符:

       std::placeholders::_1 是一个占位符,绑定函数的第一个参数,std::placeholders::_2 是一个占位符,绑定函数的第二个参数,std::placeholders::_n 是一个占位符,绑定函数的第 n 个参数。

二   源码 

2.1    std::function

template<typename _Signature>class function;/***  @brief Primary class template for std::function.*  @ingroup functors**  Polymorphic function wrapper.*/template<typename _Res, typename... _ArgTypes>class function<_Res(_ArgTypes...)>: public _Maybe_unary_or_binary_function<_Res, _ArgTypes...>,private _Function_base{template<typename _Func,typename _Res2 = typename result_of<_Func&(_ArgTypes...)>::type>struct _Callable : __check_func_return_type<_Res2, _Res> { };// Used so the return type convertibility checks aren't done when// performing overload resolution for copy construction/assignment.template<typename _Tp>struct _Callable<function, _Tp> : false_type { };template<typename _Cond, typename _Tp>using _Requires = typename enable_if<_Cond::value, _Tp>::type;public:typedef _Res result_type;// [3.7.2.1] construct/copy/destroy/***  @brief Default construct creates an empty function call wrapper.*  @post @c !(bool)*this*/function() noexcept: _Function_base() { }/***  @brief Creates an empty function call wrapper.*  @post @c !(bool)*this*/function(nullptr_t) noexcept: _Function_base() { }/***  @brief %Function copy constructor.*  @param __x A %function object with identical call signature.*  @post @c bool(*this) == bool(__x)**  The newly-created %function contains a copy of the target of @a*  __x (if it has one).*/function(const function& __x);/***  @brief %Function move constructor.*  @param __x A %function object rvalue with identical call signature.**  The newly-created %function contains the target of @a __x*  (if it has one).*/function(function&& __x) noexcept : _Function_base(){__x.swap(*this);}/***  @brief Builds a %function that targets a copy of the incoming*  function object.*  @param __f A %function object that is callable with parameters of*  type @c T1, @c T2, ..., @c TN and returns a value convertible*  to @c Res.**  The newly-created %function object will target a copy of*  @a __f. If @a __f is @c reference_wrapper<F>, then this function*  object will contain a reference to the function object @c*  __f.get(). If @a __f is a NULL function pointer or NULL*  pointer-to-member, the newly-created object will be empty.**  If @a __f is a non-NULL function pointer or an object of type @c*  reference_wrapper<F>, this function will not throw.*/template<typename _Functor,typename = _Requires<__not_<is_same<_Functor, function>>, void>,typename = _Requires<_Callable<_Functor>, void>>function(_Functor);/***  @brief %Function assignment operator.*  @param __x A %function with identical call signature.*  @post @c (bool)*this == (bool)x*  @returns @c *this**  The target of @a __x is copied to @c *this. If @a __x has no*  target, then @c *this will be empty.**  If @a __x targets a function pointer or a reference to a function*  object, then this operation will not throw an %exception.*/function&operator=(const function& __x){function(__x).swap(*this);return *this;}/***  @brief %Function move-assignment operator.*  @param __x A %function rvalue with identical call signature.*  @returns @c *this**  The target of @a __x is moved to @c *this. If @a __x has no*  target, then @c *this will be empty.**  If @a __x targets a function pointer or a reference to a function*  object, then this operation will not throw an %exception.*/function&operator=(function&& __x) noexcept{function(std::move(__x)).swap(*this);return *this;}template<typename _Functor>_Requires<_Callable<typename decay<_Functor>::type>, function&>operator=(_Functor&& __f){function(std::forward<_Functor>(__f)).swap(*this);return *this;}/// @overloadtemplate<typename _Functor>function&operator=(reference_wrapper<_Functor> __f) noexcept{function(__f).swap(*this);return *this;}/***  @brief Invokes the function targeted by @c *this.*  @returns the result of the target.*  @throws bad_function_call when @c !(bool)*this**  The function call operator invokes the target function object*  stored by @c this.*/_Res operator()(_ArgTypes... __args) const;};

2.2    std::bind

// Trait type used to remove std::bind() from overload set via SFINAE// when first argument has integer type, so that std::bind() will// not be a better match than ::bind() from the BSD Sockets API.template<typename _Tp, typename _Tp2 = typename decay<_Tp>::type>using __is_socketlike = __or_<is_integral<_Tp2>, is_enum<_Tp2>>;template<bool _SocketLike, typename _Func, typename... _BoundArgs>struct _Bind_helper: _Bind_check_arity<typename decay<_Func>::type, _BoundArgs...>{typedef typename decay<_Func>::type __func_type;typedef _Bind<__func_type(typename decay<_BoundArgs>::type...)> type;};// Partial specialization for is_socketlike == true, does not define// nested type so std::bind() will not participate in overload resolution// when the first argument might be a socket file descriptor.template<typename _Func, typename... _BoundArgs>struct _Bind_helper<true, _Func, _BoundArgs...>{ };/***  @brief Function template for std::bind.*  @ingroup binders*/template<typename _Func, typename... _BoundArgs>inline typename_Bind_helper<__is_socketlike<_Func>::value, _Func, _BoundArgs...>::typebind(_Func&& __f, _BoundArgs&&... __args){typedef _Bind_helper<false, _Func, _BoundArgs...> __helper_type;return typename __helper_type::type(std::forward<_Func>(__f),std::forward<_BoundArgs>(__args)...);}template<typename _Result, typename _Func, typename... _BoundArgs>struct _Bindres_helper: _Bind_check_arity<typename decay<_Func>::type, _BoundArgs...>{typedef typename decay<_Func>::type __functor_type;typedef _Bind_result<_Result,__functor_type(typename decay<_BoundArgs>::type...)>type;};/***  @brief Function template for std::bind<R>.*  @ingroup binders*/template<typename _Result, typename _Func, typename... _BoundArgs>inlinetypename _Bindres_helper<_Result, _Func, _BoundArgs...>::typebind(_Func&& __f, _BoundArgs&&... __args){typedef _Bindres_helper<_Result, _Func, _BoundArgs...> __helper_type;return typename __helper_type::type(std::forward<_Func>(__f),std::forward<_BoundArgs>(__args)...);}

三   使用例子

 

#include<iostream>
#include<functional>int (*func_ptr)(int);int func(int a)
{std::cout << "func: " << a << endl;return a;
}void f(int n1, int n2, int n3, const int& n4, int n5) {std::cout << n1 << ' ' << n2 << ' ' << n3 << ' ' << n4 << ' ' << n5 << std::endl;
}template<typename T>
T fun2(T a){return a + 2;
}struct my_add{int operator()(int x){return x + 9;}
};struct Foo
{static void func11(){std::cout << "static void func1......" << std::endl;}static void func12(int val){std::cout << "static void func1( val "<< val << "......" << std::endl;}void func2(int val){std::cout << "void func2(val "<< val << ")......" << std::endl;}};int main()
{// 1. 包装函数std::function<int(int)>  f1 = func;f1(66);std::cout << sizeof (f1) << std::endl;// 2. 包装函数指针func_ptr = func;func_ptr(88);// 3. 包装模板函数f1 = fun2<int>;f1(688);// 4. 包装仿函数f1 = my_add();std::cout << f1(87) << std::endl;// 5. 包装lambda 函数auto tmp_func = [](int a)->int{return a;};f1 = tmp_func;std::cout << f1(8888) << std::endl;// 6 包装静态函数std::function<void(void)> f61 = Foo::func11;f61();std::function<void(int)>  f62 = Foo::func12;f62(666);// 7 包装类成员函数Foo foo;std::function<void(int)> f7 = std::bind(&Foo::func2, foo, std::placeholders::_1);f7(888);// bindauto f2 = std::bind(f, std::placeholders::_3, std::placeholders::_2, std::placeholders::_1, 4, 5);f2(3, 2, 1);std::function<void(int, int, int)> ff = f2;ff(3, 2, 1);std::cout << "------ main end ------" << std::endl;return 0;
}

输出:

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

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

相关文章

CHAPTER 11: 《DESIGN A NEWS FEED SYSTEM》 第 11 章:《设计新闻系统》

在本章中&#xff0c;您将被要求设计一个新闻提要系统。什幺是新闻系统&#xff1f;根据Facebook 页面&#xff0c;“News feed 是中间不断更新的故事列表。您的主页。动态消息包括状态更新、照片、视频、链接、应用活动记录和喜欢您在 Facebook 上关注的人、页面和群组“[1]。…

Mysql运维篇(三) MySQL数据库分库分表方案

一路走来&#xff0c;所有遇到的人&#xff0c;帮助过我的、伤害过我的都是朋友&#xff0c;没有一个是敌人&#xff0c;如有侵权请留言&#xff0c;我及时删除。 一、前言 关系型数据库本身比较容易成为系统瓶颈&#xff0c;单机存储容量、连接数、处理能力都有限。当单表的数…

磁盘的分区与文件系统的认识

磁盘的认识 了解磁盘的结构&#xff1a; 1、盘片 硬盘首先会有多个盘片构成&#xff0c;类似很多个独立的光盘合并在一起&#xff0c;每个盘片都有2个面&#xff0c;每个盘片都有一个对应的磁头&#xff0c;我们的磁头横移和盘面的旋转就可以读写到盘面的每一个位置&#xff0c…

08. 面向对象编程(二)

目录 1、前言 2、多重继承 2.1、潜在的问题 3、Property 4、staticmethod 5、运算符重载 5.1、加法运算符 的重载 5.2、字符串表示运算符 str() 的重载 5.3、索引运算符 [] 的重载 6、小结 1、前言 上一篇文章中&#xff0c;我们介绍了面向对象编程的类和实例&…

v35-36.problems

1.size of&#xff08;&#xff09;运算符 根据c语言标准规范&#xff0c;Size of&#xff08;&#xff09; 里面的操作数如果不是可变长度数组类型 &#xff0c;那么此操作数就不会被执行 &#xff01;

x-cmd pkg | skate - 个人键值对存储工具

目录 简介用户首次快速实验指南功能特点竞品和相关作品进一步探索 简介 skate 是个人键值对存储工具&#xff0c;具备数据加密、云端数据备份以及多设备同步等功能。 它由 Charm 团队开发&#xff0c;借用 Charm Cloud 向用户提供一种快捷的方式来保存和检索各种数据&#xf…

零基础学习【Linux】这一篇就够了

Linux学习目录 1. Linux简介1-1. Linux系统版本 2. Linux安装2-1. 安装方式2-2. Vmware安装2-3. Linux安装2-4. Vmware克隆2-5. Vmware快照2-6. 连接工具安装 3. Linux常用命令4. Linux软件安装5. 项目部署 1. Linux简介 1-1. Linux系统版本 Linux系统分为内核版和发行版 内核…

「斗破年番」大紫研爆虐六星斗皇,佛怒火连回归,异火焚烧分身

Hello,小伙伴们&#xff0c;我是拾荒君。 国漫《斗破苍穹年番》第80期超前爆料&#xff0c;据透露韩枫以海心焰这一异火贡献给了慕骨老人&#xff0c;换取了一具斗宗躯体。通过灵魂融入&#xff0c;他成功达到了斗宗四星阶段。而与小医仙对决的莫天行&#xff0c;尽管两人实力…

Java设计模式详解-更新中

收藏和关注的同时&#xff0c;请也关注 公众号 “IT技术馆” 各位大家好&#xff0c;从今天开始&#xff0c;作者开始整理 《JAVA软件设计模式&#xff08;GOF&#xff09;》 专栏。请各位多多关注&#xff01; 该专栏是根据作者的技术经验和设计模式的了解&#xff0c;进行详…

从零开始c++精讲:第三篇——内存管理

文章目录 一、C/C内存分布二、C语言中动态内存管理方式:malloc/calloc/realloc/free三、C中动态内存管理四、operator new与operator delete函数4.1 operator new与operator delete函数&#xff08;重点&#xff09; 五、new和delete的实现原理5.1内置类型5.2 自定义类型 六、定…

代码随想录二刷 | 回溯 | 组合优化

代码随想录二刷 &#xff5c; 回溯 &#xff5c; 组合优化 剪枝优化 剪枝优化 在遍历的过程中有如下代码&#xff1a; for (int i startIndex; i < n; i) {path.pop_back();backtracking(n, k, i 1);path.pop_back(); }n 4&#xff0c;k 4的话&#xff0c;那么第一层f…

打折:阿里云国外服务器价格购买优惠活动

阿里云国外服务器优惠活动「全球云服务器精选特惠」&#xff0c;国外服务器租用价格24元一个月起&#xff0c;免备案适合搭建网站&#xff0c;部署独立站等业务场景&#xff0c;阿里云服务器网aliyunfuwuqi.com分享阿里云国外服务器优惠活动&#xff1a; 全球云服务器精选特惠…

idea 折叠某段代码 这段特定某段代码

如何折叠IntelliJ IDEA代码片段_w3cschool ctrlALTT

圆的参数方程是如何推导的?

圆的参数方程是如何推导的? 1. 圆的三种参数表示2. 三角函数万能公式3. 回到圆的参数方程1. 圆的三种参数表示 已知圆的第一种参数方程为: x 2 + y 2 = r x^2+y^2=r x2+y2=r   圆的图像如下: 通过上图,不难理解,圆的参数方程还可以用三角函数表示,也就是第二种参数表…

计算机毕业设计 | SpringBoot学生成绩管理系统(附源码)

1&#xff0c; 概述 1.1 课题背景 开发一个学生成绩管理系统&#xff0c;采用计算机对学生成绩进行处理&#xff0c;进一步提高了办学效益和现代化水平。为广大教师和学生提高工作效率&#xff0c;实现学生成绩信息管理工作流程的系统化、规范化和自动化。现在我国中学的学生…

基于STM32CubeMX创建FreeRTOS—以STM32F429为例

目录 1. 实验任务 2. 使用STM32CubeMX创建基础工程 2.1 打开STM32CubeMX 2.2 创建新项目 2.3 时钟设置 2.5 修改时钟基准&#xff0c;打开串行调试 2.6 配置串口 2.7 配置状态指示灯 2.8 FreeRTOS 2.9 配置工程输出项 3. 代码编辑 3.1 printf重映射 3.1.1 使用ARM…

【JavaEE】网络初识 (IP地址, 端口号, 协议, 封装和分用)

文章目录 前言网络通信基础一.IP地址概念格式特殊IP 二.端口号概念注意事项 三.协议概念知名协议的默认端口五元组协议分层OSI七层模型TCP/IP五层模型 四.封装和分用 前言 本章来介绍一下网络中的一些基本概念, 例如 : IP地址, 端口号, 协议, 协议分层, 封装, 分用等等. 网络…

计组原理:系统概论与基本组成

系统概论与基本组成 系统概论硬件软件 计算机系统的层次结构系统复杂性的管理方法1&#xff1a;抽象 计算机的基本组成冯诺依曼计算机系统复杂性的管理方法 2&#xff1a;&#xff08;3’Y&#xff09; 计算机的工作步骤上机前的准备&#xff1a;计算机的解题过程存储器的基本组…

AI教我学编程之C#类的实例化与访问修饰符

前言 在这篇文章中&#xff0c;我将带大家深入了解C#编程语言的核心概念&#xff0c;包括类的实例化、访问修饰符的应用&#xff0c;以及C#中不同数据类型的默认值。我会通过逐步分析和具体实例&#xff0c;详细解释如何在C#中正确创建和操作对象&#xff0c;并探讨如何通过访…

维基百科推广的12种方法帮你建立强大的品牌-华媒舍

维基百科是全球最大、最权威的多语言网络百科全书。它是许多人搜索信息、获取知识的首选平台&#xff0c;也是许多品牌建立强大影响力的重要途径。本文将介绍维基百科推广的12种方法&#xff0c;帮助你在维基百科上建立强大的品牌形象。 1. 准备工作 在开始维基百科推广之前&a…