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

news2024/9/21 8:00:20

一  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;
	}

      /// @overload
      template<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...>::type
    bind(_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>
    inline
    typename _Bindres_helper<_Result, _Func, _BoundArgs...>::type
    bind(_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);


     // bind
     auto 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.coloradmin.cn/o/1398672.html

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

相关文章

英国金融时报关注TRX登陆Mercado Bitcoin交易所:波场TRON强化南美洲布局,国际化进程持续加速

近日,波场TRON网络原生代币TRX正式上线巴西最大的合规加密交易所Mercado Bitcoin。英国金融时报、Decrypt、Blockworks等财经及加密行业权威媒体对该话题进行了报道,表示此次合作是波场TRON全球业务增长的有力证明,也表明该平台力求处于数字经济前沿的坚定决心。 据悉,Mercado…

小白快速上手maven【基础篇】

Maven的概念和作用 Maven是什么&#xff1f;POM的概念 Maven的作用&#xff1f; 提供自动化构建项目的方式&#xff0c;并且统一了项目的结构管理项目中的依赖 Maven基础概念-仓库&#xff0c;坐标&#xff0c;仓库配置 仓库&#xff1a;用于存储各种jar包资源 根据功能的不…

【微信小程序开发】环境介绍和基本使用

文章目录 前言1. 项目的基本组成结构1.1 JSON 配置文件的作用1.2 如何新建小程序页面1.3 修改项目首页1.4 WXML 模板1.5 WXSS 样式1.6 JS 逻辑交互 2. 宿主环境2.1 什么是宿主环境2.2 通信模型2.3 运行机制2.4 组件2.4.1 view 组件的基本使用&#xff1a;2.4.2 scroll-view 组件…

专业137总分439东南大学920专业基础综合考研经验电子信息与通信电路系统芯片

我本科是南京信息工程大学&#xff0c;今年报考东南大学信息学院&#xff0c;成功逆袭&#xff0c;专业137&#xff0c;政治69&#xff0c;英语86&#xff0c;数一147&#xff0c;总分439。以下总结了自己的复习心得和经验&#xff0c;希望对大家复习有一点帮助。啰嗦一句&…

OpenAI CEO称“AGI时代”即将来临,下一个风口或为能源领域

原创 | 文 BFT机器人 在最近的达沃斯论坛上&#xff0c;Sam Altman以其深邃的见解和前瞻性的思考&#xff0c;再次成为了全场关注的焦点。他以一场激情四溢的演讲&#xff0c;深入剖析了人工智能技术的未来发展趋势&#xff0c;以及它可能对社会和工作领域产生的深远影响。 Al…

HTTP 协议和 TCP/IP 协议之间有什么区别?

HTTP&#xff08;超文本传输协议&#xff09;和TCP/IP&#xff08;传输控制协议/互联网协议&#xff09;是两种在互联网通信中广泛使用的协议&#xff0c;它们之间的区别和联系对许多人来说可能还不是很清晰&#xff0c;今天我们就带大家来一起了解一下HTTP和TCP/IP协议这2者之…

JAVAEE初阶 封装与分用

封装和分用 一.封装1.1 应用层1.2 传输层1.3 网络层1.4 数据链路层1.5 物理层 二.分用2.1 物理层2.2 数据链路层2.3 网络层2.4 传输层2.5 应用层 三. 交换机的封装分用四.路由器的封装分用五. 网络中数据传输的单位 在讲解封装与分用前&#xff0c;我们需要先说明一个例子。 例…

【Qt】ubuntu环境下使用命令行安装Qt

起因是我上一篇文章说的&#xff0c;官网下的安装包卡死在第一步安装界面了。 于是我就问GPT有没有纯命令行的安装方式&#xff0c;果然是有的。 在Ubuntu上安装Qt可以使用以下命令&#xff1a; 1. 首先&#xff0c;添加Qt的官方存储库到系统中&#xff1a; sudo add-apt-rep…

如何进行产品的人机交互设计?

产品的人机交互设计是指通过用户界面和用户体验设计来优化产品与用户之间的交互过程&#xff0c;从而提高产品的易用性、可用性和用户满意度。人机交互设计需要考虑用户的需求、行为模式、心理感受以及技术实现&#xff0c;下面我将介绍如何进行产品的人机交互设计。 首先&…

汇川PLC如何连接电脑进行数据通信和远程上下载

准备工作 一台可联网操作的电脑一台单网口的远程透传网关及博达远程透传配置工具网线一条&#xff0c;用于实现网络连接和连接PLC一台汇川PLC及其编程软件InoPrShop一张4G卡或WIFI天线实现通讯(使用4G联网则插入4G SIM卡&#xff0c;WIFI联网则将WIFI天线插入USB口&#xff09…

国科大模式识别与机器学习2015-2019、2021、2023仅考题

2015 &#xff08;8&#xff09;试描述线性判别函数的基本概念&#xff0c;并说明既然有线性判别函&#xff0c;为什么还需要非线性判别函数&#xff1f;假设有两种模式&#xff0c;每类包括6个4维不同的模式&#xff0c;且良好分布。如果他们是线性可分的。问权向量至少需要几…

phpmyadmin 创建服务器

phpmyadmin默认的服务器是localhost 访问setup&#xff0c;创建新的服务器 添加服务器信息 点击应用&#xff0c;服务器创建成功 下载配置文件config.inc.php&#xff0c;放到WWW目录下 可再次访问setup&#xff0c;发现已配置过了 访问登录页面&#xff0c;发现可选…

Python利用Excel读取和存储测试数据完成接口自动化教程

http_request2.py用于发起http请求 #读取多条测试用例#1、导入requests模块import requests#从 class_12_19.do_excel1导入read_data函数from do_excel2 import read_datafrom do_excel2 import write_datafrom do_excel2 import count_case#定义http请求函数COOKIENonedef ht…

Linux 查看时区及修改时区的方法

查看时区 ll /etc/localtime可以看到这里显示的是纽约的时区 修改时区 timedatectl set-timezone Asia/Shanghai如图所示&#xff0c;表示修改成功为上海时区

zookeeper window 安装

下载 Apache ZooKeeper 解压Zookeeper安装包到指定目录&#xff0c;注意目录不要有空格。 备份zoo_sample.cfg并改名zoo.cfg 注意&#xff1a;此处的路径一定要使用双斜杠" \\ " D:\\apache-zookeeper-3.8.3-bin\\data 新建环境变量&#xff1a;ZOOKEEPER_HOME D…

HBase学习五:运维排障

1、负载均衡 1.1 Rgion迁移 在当前的HBase版本中,Region迁移虽然是一个轻量级操作,但实现逻辑依然比较复杂,≈复杂性主要表现在两个方面:其一,Region迁移过程涉及多种状态的改变;其二,迁移过程中涉及Master、ZooKeeper(ZK)以及RegionServer等多个组件的相互协调。 …

Linux 【C编程】 引入线程,线程相关函数

1.线程的引入 1.1使用线程同时读取键盘和鼠标 代码演示&#xff1a; #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <unistd.h> #include <termios.h> #include <fcntl.h> #include <string.h> // 读取…

可视化 | 【echarts】渐变条形+折线复合图

文章目录 &#x1f4da;html css&#x1f4da;js&#x1f407;总体框架&#x1f407;option配置项 &#x1f4da;html css html&#xff1a;在这主要是用于整合&#xff0c;将html、css、js连接在一块&#xff0c;虽然单个模板代码量不大&#xff0c;但还是先分开&#xff0…

AI嵌入式K210项目(13)-Camera

文章目录 前言一、硬件介绍二、K210对硬件的支持实验过程总结 前言 我们这款开发板应该是最便宜的AI开发板了吧&#xff0c;200RMB左右&#xff0c;搭载1TOPS处理能力的K210芯片&#xff0c;丰富的外设接口&#xff0c;内置超多算法&#xff0c;除此之外&#xff0c;开发板还带…

重学Java 10 面向对象

正是风雨欲来的时候&#xff0c;火却越烧越旺了 ——24.1.20 重点 1.为何使用面向对象思想编程 2.如何使用面向对象思想编程 3.何时使用面向对象思想编程 4.利用代码去描述世间万物的分类 5.在一个类中访问另外一个类中的成员 -> new对象 6.成员变量和局部变量的区别 一…