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.hqwc.cn/news/417653.html

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

相关文章

day24 回溯算法 组合

题目1&#xff1a;77 组合 题目链接&#xff1a;77 组合 题意 返回[1,n]中k个数的组合 元素不可以重复使用 回溯 回溯三部曲 1&#xff09;参数和返回值 void n k 2&#xff09;终止条件 叶子节点的大小为2 终止&#xff0c;放到数组中 3&#xff09;单层递归逻辑…

23级应届生如何找java工作?

Java应届生找工作&#xff0c;不能单靠背面试题&#xff0c;更不能在简历中堆砌和找工作关系不大的校园实践经历&#xff0c;而是更要在面试中能证明自己的java相关商业项目经验。其实不少应届生Java求职者不是说没真实Java项目经验&#xff0c;而是不知道怎么挖掘&#xff0c;…

Redis主从架构、哨兵集群原理实战

1.主从架构简介 背景 单机部署简单&#xff0c;但是可靠性低&#xff0c;且不能很好利用CPU多核处理能力生产环境必须要保证高可用&#xff0c;一般不可能单机部署读写分离是可用性要求不高、性能要求较高、数据规模小的情况 目标 读写分离&#xff0c;扩展主节点的读能力&…

【加强版】小学数学出题,加减乘除混合运算,支持自定义数字,一键打印

在线预览&#xff1a;在线HTML代码预览和运行工具 - UU在线工具 复制下面代码后到该地址预览即可 注意&#xff1a;在线预览不能打印。如需打印&#xff0c;在电脑本地上新建文本文档&#xff0c;粘贴代码后保存&#xff0c;然后把文件后缀改为.html运行&#xff0c;出题点击…

力扣刷MySQL-第六弹(详细讲解)

&#x1f389;欢迎您来到我的MySQL基础复习专栏 ☆* o(≧▽≦)o *☆哈喽~我是小小恶斯法克&#x1f379; ✨博客主页&#xff1a;小小恶斯法克的博客 &#x1f388;该系列文章专栏&#xff1a;力扣刷题讲解-MySQL &#x1f379;文章作者技术和水平很有限&#xff0c;如果文中出…

单页面vite打包学习

前端工程化本人真的很发怵&#xff0c;一直也没有专心去突破一下&#xff0c;都是能用就用&#xff0c;所以今天小小学习一下打包&#xff0c;先从单页面应用的vite打包开始。本文主要是一些我的大白话和有限的经验&#xff0c;如有问题望指正。 一、问题 网页要从服务器请求…

Crow:实现点击下载功能

Crow:设置网站的index.html-CSDN博客 讲述了如何完成一个最简单的网页的路由 很多网页提供了下载功能,怎么实现呢,其实也很简单。 假设网页的目录结构如图 $ tree static static ├── img │ └── goodday.jpg └── index.html //index.html <html> <body&…

近期学习文章

DNSlog在渗透测试中的实战技巧 - 网安隐藏源IP&#xff0c;提高溯源难度的几种方案 - 网安FreeBuf网络安全行业门户 【漏洞公告】某平台一个有意思的CSRF // SecTrain安全博客 浅谈Web源码泄漏-安全客 - 安全资讯平台 红队-C2 Server基础构建 - 先知社区FreeBuf网络安全行业…

力扣每日一题---1547. 切棍子的最小成本

//当我们将棍子分段之后&#xff0c;我们是不是想到了怎么组合这些棍子 //并且这些棍子有一个性质就是只能与相邻的进行组合 //暴力搜索的话复杂度很高 //在思考暴力搜索的时候&#xff0c;我们发现一个规律 //比如棍子长度1 2 1 1 2 //那么与最后一个2组合的棍子有&#xff0c…

Java毕业设计-基于ssm的网上求职招聘管理系统-第85期

获取源码资料&#xff0c;请移步从戎源码网&#xff1a;从戎源码网_专业的计算机毕业设计网站 项目介绍 基于ssm的网上求职招聘管理系统&#xff1a;前端 jsp、jquery&#xff0c;后端 springmvc、spring、mybatis&#xff0c;角色分为管理员、招聘人员、用户&#xff1b;集成…

关于大模型学习中遇到的3

来源&#xff1a;网络 Embedding模型 随着大型语言模型的发展&#xff0c;以ChatGPT为首&#xff0c;涌现了诸如ChatPDF、BingGPT、NotionAI等多种多样的应用。公众大量地将目光聚焦于生成模型的进展之快&#xff0c;却少有关注支撑许多大型语言模型应用落地的必不可少的Embed…

linux 安装nginx

介绍 官网 https://nginx.org/en/download.html 在安装nginx前首先要确认系统中安装了gcc、pcre-devel、zlib-devel、openssl-devel linux 检查是否安装过某软件包 yum -y install gcc pcre-devel zlib-devel openssl openssl-devel #下载 wget https://nginx.org/downloa…