【C++ STL学习与应用总结】22: 函数组合之1:如何使用std::bind (since C++11)

【C++ STL学习与应用总结】22: 函数组合之1:如何使用std::bind (since C++11)

标签: c++stl
  8842人阅读  评论(0)  收藏  举报
  分类:
 

目录(?)[+]

本系列文章的目录在这里:目录. 通过目录里可以对STL总体有个大概了解

前言

std::bind是STL实现函数组合概念的重要手段,本文总结了std::bind这个模板函数的用法,给出了std::bind绑定普通函数(函数指针)、lambda表达式、成员函数、成员变量、模板函数、嵌套std::bind等的语法细节及注意的问题。

文中涉及到的术语:

  • std::placeholders : 占位符,被占位符绑定的参数,在实际调用中被实际参数代替。

  • std::decay : 退化类型

  • std::forward : 转发

  • Callable : 可调用对象

  • lambda : functors的语法糖,定义一个函数(对象), 当做函数来使用

  • trailing return types : 用于在声明(定义)函数时,函数返回值依赖于其参数的类型;或者是函数返回类型描述比较复杂时,用来简化类型书写

  • reference_wrapper : 引用包装类模板,用于把一个应用封装成一个对象,以便于在容器里,或者传递引用。

std::bind 是什么

看命名空间前缀std就知道,bind是标准库的亲儿子,包含在<functional>中.

std::bind 是一个函数模板, 它就像一个函数适配器,可以把一个原本接收N个参数的函数fn,通过绑定一些参数,返回一个接收M个参数的函数ret,同时还可以实现参数顺序调整等操作。

它的原型有两种形式,如下:

原型

<code class="language-c++ hljs r has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">// simple(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>)    
template <class Fn, class... Args>
  /* unspecified */ bind (Fn&& fn, Args&&<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span> args);

 // with <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> type (<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>)    
template <class Ret, class Fn, class... Args>
  /* unspecified */ bind (Fn&& fn, Args&&<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span> args);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul>

bind返回一个基于fn的函数对象(function object), 其参数被绑定到args上.

fn的参数要么是绑定到值,要么是绑定到placeholders(占位符,如_1, _2, …, _N)

参数:

  • fn: 一个Callable对象(可以是function objects, 函数指针或引用,成员函数指针或成员变量指针), 它的参数将被args绑定

  • args: 可变长参数,或者是具体的值,或者是占位符(placeholder)注意:其长度必须与fn接收的参数个数一致

返回值

令bind的返回值为ret:

<code class="language-c++ hljs r has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">auto ret = std::bind(fn, args&&<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span>)
// or
auto ret = std::bind<Ret>(fn, args&&<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span>)</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>

其返回值ret是一个未指定类型T的function object,T满足如下条件:std::is_bind_expression<T>::value == true.

ret这个类型,包含如下的成员:

1.成员变量:

  • 1: decay<Fn>::type类型的对象(暂且叫_Myfun), 由std::forward<Fn>(fn)构造得来。简单来说,就是保存了bind时候传过来的fn对象.

  • 2: tuple<typename decay<Types>::type> 类型的对象(暂且叫它_Mybargs), 这个tuple的每个元素的类型是decay<Args_i>::type, 是由调用bind时,第二个参数args…转发而来, 即forward<Args_i>(arg_i), Args_i 表示args中的第i个. 通俗来说,这个对象保存了bind时传过来的所有的参数args…。

ret的这个两个成员对象分别保存了bind传来的函数和参数以实现将来的调用任务。

2. 构造函数:

  • 如果ret的所有成员对象都是可以拷贝构造的,那么它自身也是可拷贝构造的

  • 同理,如果所有成员都是可移动构造的,那么它自身也是可移动构造的

3. 成员类型:result_type

  • 如果Fn是一个函数指针或者成员函数指针,那么ret的result_type就是Fn的返回值类型.

  • 如果Fn是一个类,并且它内部定义了一个result_type, 那么result_type就等于Fn::result_type.

  • 如果ret是使用第二种形式调用bind得到的,即auto ret = bind<Ret>(fn , args), 那么result_type就是Ret.

4. 成员函数 operator() (此为重点,毕竟bind的返回值ret,就是用来当做函数调用的

ret作为bind的返回值,假设我们这样调用ret: ret(a1, a2, a3, … ai); 此时ret内部保存的那个decay<Fn>::type类型的对象:_MyFun, 将被调用, 它将会按照如下的方式来为a1, a2, …, ai 来绑定值:

  • 如果调用bind时指定的是reference_wrapper<T>类型的,比如在调用bind时使用了std::ref 或者 std::cref来包装args,那么调用ret内部的_MyFun时,对应参数会以T&类型传入_MyFun.

  • 如果在创建ret时候,使用了嵌套的bind,即ret = bind(fn, args…)的参数列表args中,存在某个arg:使得std::is_bind_expression<decltype(arg)>::value == true, 那么这个嵌套的bind表达式会被立即调用,其返回值会被传给ret里的_MyFun作为参数(也就是说嵌套的bind返回值会被当做ret调用时的参数), 如果嵌套的bind里用到了占位符placeholder, 这些placeholder将会从ret的调用参数ret(a1, a2, … ai)中对应位置选择.

  • 如果在创建ret时候,使用了占位符placeholders, 即 ret = bind(fn, arg1, arg2, …, _1, _2, …), (对于_1, _2…, 有std::is_placeholder<T>::value != 0). 那么a1, a2, …, ai会以转发的形式forward<ai>(ai)传递给_MyFun, a1对应_1, a2对应_2, 以此类推.

  • 否则,ret内部保存的args,即上文提到的_Mybargs(bind调用时绑定的参数们)将被以左值的形式传给_MyFun以完成调用,这些参数和g有相同cv限定属性.

如果g(a1, a2, …, ai)中,有哪些ai没有匹配任何的placeholders,比如在调用bind时,placeholder只有_1, 而g(a1, a2, a3), 那么a2, a3就是没有匹配的,没有被匹配的参数将被求值,但是会被丢弃。

如果g被指定为volatile(volatile or const volatile),结果是未定义的.

“说了那么多,你就是想装b”, 还是看看bind在实际代码中的应用吧

从两个极端情况出发,正确理解bind过程和std::placeholders的使用

为了更容易理解并使用bind,再强调一下这句话:fn的参数要么是绑定到值,要么是绑定到placeholders

极端1:完全绑定到值

<code class="language-c++ hljs cpp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> f(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> n1, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> n2, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> n3)
{
    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cout</span> << n1 << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">" "</span> << n2 << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">" "</span> << n3 << endl;
}

<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// f的三个参数,全部绑定到值,对empty_args的调用将不需要提供参数</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">auto</span> empty_args = bind(f, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>);     
empty_args();               <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 1 2 3</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li></ul>

极端2:完全绑定到std::placeholders

<code class="language-c++ hljs cpp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> f(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> n1, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> n2, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> n3)
{
    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cout</span> << n1 << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">" "</span> << n2 << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">" "</span> << n3 << endl;
}

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> ret4() 
{ 
    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cout</span> << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"ret4() called"</span> << endl;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span>; 
}

<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// f参数都使用占位符绑定, 需要提供至少三个参数</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">auto</span> need_3args = bind(f, _1, _2, _3);
need_3args(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>);            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 1 2 3</span>
need_3args(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>);      <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 1 2 3; 4和5被丢弃</span>
need_3args(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>, ret4());    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// ret4() called<cr> 1 2 3; 会调用ret4(), 但是返回的4被丢弃</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li></ul>

除了这两种极端的情况,大部分情形下,bind是混合着值和占位符来进行绑定的。

bind过程分析及调用传参控制

在分析bind的绑定过程时,如何确定bind调用有没有错误,以及调用bind返回值ret的时候如何正确传参?比如,对下面的bind调用:

<code class="language-c++ hljs r has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">void f(int n1, int n2, int n3, int n4, int n5)
{
    cout << n1 << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">" "</span> << n2 << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">" "</span> << n3 << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">" "</span> << n4 << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">" "</span> << n5 << endl;
}

// 如何分析bind的调用是否正确
auto mix1 = bind(f, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>, _<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, _<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>);
auto mix2 = bind(f, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span>, _<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, _<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>);
auto mix3 = bind(f, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>, _<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, _<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);
auto mix4 = bind(f, _<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span>, _<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);
auto mix5 = bind(f, _<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, _<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, _<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, _<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, _<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);
auto mix6 = bind(f, _<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>, _<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">50</span>, _<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>, _<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>, _<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);


// 如何填写mix的调用参数,他需要几个参数?
// mix1(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span>); 
// mix3(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span>); 
// mix4(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span>); 
// mix5(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span>); </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li></ul>

分析过程:

1. bind(f, args…)的合法性分析

设f需要的参数个数为N, bind(f…)中,提供的值的个数为V, 提供的占位符个数为S.

对于合法的bind调用,必有 N == V + S. 如果V + S 超出N或者小于N, 编译都会报错。

所以上面的mix定义中,只有mix1, mix3, mix4, mix5是合法的。mix2中参数个数已经有6个,而f只需要5个。mix6的参数个数对,但是占位符太大了, 在VC++(2013)编译器实现中最大为20。

2. bind返回值ret的调用传参写法

设bind(f, args…)中最大的占位符为_M. ( 如mix1, mix2, mix3中 M=2; mix4中 M=3; mix5中 M=1; mix6中M=100; )

则:

  • 参数个数

    ret的调用中至少要提供 M 个参数,因为_1~_M正是从ret(args…)参数列表中从左到右来按下标顺序绑定参数的,少于M个会报错,多于M个则被丢弃.

  • 参数顺序

    ret(args…)中参数与placeholders: _1~_M的对应是很简单的,下标从1开始,依次对应。但是绑定到f的顺序是由bind(fn, args…)中placeholders的顺序决定的.如bind(f, _1, _2, _3, _4, _5)就是从左到右的顺序把ret(args…)里的参数绑定到f;而bind(f, _5, _4, _3, _2, _1)则是按相反的顺序绑定。

于是,对于上文中定义的合法mix的调用示例及输出可以是:

<code class="language-c++ hljs d has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">auto</span> mix1 = bind(f, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>, _1, _2);
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">auto</span> mix3 = bind(f, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>, _2, _1);
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">auto</span> mix4 = bind(f, _3, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span>, _1);
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">auto</span> mix5 = bind(f, _1, _1, _1, _1, _1);

mix1(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>);                 <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 1 2 3 4 5; M = 2;</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//mix1(4);                  // no, 参数太少了</span>
mix3(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span>);                 <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 1 2 3 4 5; M = 2; </span>
mix4(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);              <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 1 2 3 4 5; M = 3; 第一个参数5给_1, 第三个参数1给_3, 第二个参数0被丢弃,因为bind中没用到_2.</span>
mix5(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>);                    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 5 5 5 5 5; M = 1;</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li></ul>

你可能注意到mix6中的_100, _50, 这样大的占位符是编译不过的。

placeholders的最大值,在VC++上是20, 它的最大值依赖于具体的编译器实现,不需要纠结这个最大值. 一般不会使用很大的占位符,因为一旦你使用了一个占位符_100,虽然只用了一个,但是这就意味着调用者需要提供至少100个参数,你是想弄死谁?

下面就按照fn的分类给出bind的调用示例:

std::bind 绑定普通函数、lambda表达式

<code class="language-c++ hljs cpp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include <functional></span>

<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 定义两个函数,乘、除法</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span> multiply(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span> d1, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span> d2)
{
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> d1 * d2;
}

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span> divide(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span> d1, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> n)
{
    assert(n != <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>);
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> d1 / n;
}

<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//----------------------------- begin of new test -----------------------------</span>
RUN_GTEST(FunctorTest, Bind, @);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// google gtest 的简单封装,可以当做一个普通函数的开始!</span>

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">using</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::bind;                        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// for std::bind</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">using</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">namespace</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::placeholders;      <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// for _1, _2, _3 ...</span>

<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 做“无用功”, same函数跟multiply一样,接收两个参数,并且顺序也是一致</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">auto</span> same = bind(multiply, _1, _2);
EXPECT_EQ(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">200.0</span>, same(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>));         

<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 第一个参数使用占位符,第二个单数绑定为2.0, 从而返回一个函数仅需要传入一个参数,</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 返回其2倍。</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">auto</span> doublize = bind(multiply, _1, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2.0</span>);
EXPECT_EQ(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">200.0</span>, doublize(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>));

<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 全部使用参数绑定,ret_20不需要参数即可调用,返回20</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">auto</span> ret_20 = bind(multiply, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>);
EXPECT_EQ(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">20.0</span>, ret_20());

<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 正常的相除函数, arg1/arg2</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span> d1 = divide(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>);
EXPECT_EQ(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>, d1);

<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 通过bind,交换两个参数的顺序,revertDivide(arg1, arg2)将返回arg2/arg1</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">auto</span> revertDivide = bind(divide, _2, _1);
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span> d2 = revertDivide(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>);
EXPECT_EQ(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span> / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5.0</span>, d2);

<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// bind的第二种形式,显式指定返回值类型为int</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">auto</span> rounding = bind<<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>>(divide, _1, _2);
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">auto</span> i1 = rounding(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>);
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">bool</span> isSameType = is_same<<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">decltype</span>(i1)>::value;    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// i1 是int</span>
EXPECT_TRUE(isSameType);
EXPECT_EQ(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>, i1);

<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// bind lambda函数</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">auto</span> lambda_func = [](<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> x) -> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> x; };
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">auto</span> ret_100 = bind(lambda_func, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>);
EXPECT_EQ(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>, ret_100);

<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 使用bind适配一个函数 </span>
<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::function<<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>)> func_with_1args;
func_with_1args = bind(multiply, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>, _1);

END_TEST;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li></ul>

std::bind 绑定类成员函数、成员变量

成员函数区别于普通函数的一个特殊之处在于,其第一个参数必须是该类型的一个对象(或对象的指针或引用)

<code class="language-c++ hljs cpp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> Foo
{
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span>:

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> f(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> n1, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> n2, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> n3)
    {
        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cout</span> << n1 << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">" "</span> << n2 << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">" "</span> << n3 << endl;
    }

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> a_ { <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span> };
};

<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//----------------------------- begin of new test -----------------------------</span>
RUN_GTEST(FunctorTest, Bind, @);

Foo foo;
Foo& foo_ref= foo;

<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 成员函数原型:Foo::f(int n1, int n2, int n3);</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 使用Foo::f, 需要四个参数,1.Foo类型的对象(或其指针或引用); 2~4个参数则赋值给n1, n2, n3</span>

<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 对返回值mfarg4的调用将需要4个参数: 按顺序绑定到占位符_1, _2, _3, _4.</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">auto</span> mfarg4 = bind(&Foo::f, _1, _2, _3, _4);
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 使用对象本身调用</span>
mfarg4(foo, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">20</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">30</span>);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 10 20 30; </span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 使用对象指针调用</span>
mfarg4(&foo, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">20</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">30</span>);       <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 10 20 30; </span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 使用对象引用</span>
mfarg4(foo_ref, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">20</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">30</span>);    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 10 20 30; </span>

<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 对返回值mfarg3的调用将需要三个参数:分别绑定到三个占位符,f的第四个参数将使用固定左值30.</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">auto</span> mfarg3 = bind(&Foo::f, _1, _2, _3, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">30</span>);
mfarg3(foo, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">20</span>);            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 10 20 30; </span>

<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 对返回值mfarg2的调用将需要两个参数:分别绑定到两个占位符,f的后两个参数将使用固定左值20, 30.</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">auto</span> mfarg2 = bind(&Foo::f, _1, _2, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">20</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">30</span>);
mfarg2(foo, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>);                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 10 20 30; </span>

<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 对返回值mfarg1的调用将仅需要一个参数foo对象,绑定到唯一的占位符,后单个参数将使用bind中的固定左值10,20,30.</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">auto</span> mfarg1 = bind(&Foo::f, _1, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">20</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">30</span>);
mfarg1(foo);                    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 10 20 30;</span>

<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 完全使用左值绑定,返回值mfarg0将不需要使用参数进行调用.</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">auto</span> mfarg0 = bind(&Foo::f, foo, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">20</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">30</span>);
mfarg0();                       <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 10 20 30</span>

<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 使用对象指针或引用也可以</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">auto</span> mfarg01 = bind(&Foo::f, &foo, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">20</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">30</span>);
mfarg01();                      <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 10 20 30</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">auto</span> mfarg02 = bind(&Foo::f, foo_ref, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">20</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">30</span>);
mfarg02();                      <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 10 20 30</span>

<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 把一个成员函数赋值给一个std::function</span>
<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::function<<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>)> normal_func;
normal_func = bind(&Foo::f, foo, _1, _2, _3);
normal_func(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">20</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">30</span>);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 10 20 30</span>

<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//------------------------------ 绑定成员变量a_ ---------------------------</span>

<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// bind成员变量,其第一个参数必须是该类型的一个对象(或对象或引用), 指针不行!!</span>

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">auto</span> bind_mv = bind(&Foo::a_, _1);
<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cout</span> << bind_mv(foo);           <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 100</span>
<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cout</span> << bind_mv(foo_ref);       <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 100</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//cout << bind_mv(&foo);        // error, 成员变量不能用对象指针来绑定</span>

END_TEST;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li></ul>

std::bind 绑定模板函数

<code class="language-c++ hljs cpp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 定义一个函数模板,返回两数之和,返回值是两数之和的类型。使用了c++11中的trailing return types特性.</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">template</span> <<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">typename</span> T1, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">typename</span> T2>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">auto</span> add(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> T1 & t1, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> T2& t2) -> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">decltype</span>(t1 + t2)
{
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> t1 + t2;
}

<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// work with template function.</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">auto</span> addby2 = bind(add<<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span>>, _1, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2.0</span>);
<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cout</span> << addby2(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10.2</span>);                             <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 12.2</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li></ul>

嵌套std::bind共享std::placeholder.

<code class="language-c++ hljs cpp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> print(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> n1, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> n2, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> n3)
{
    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cout</span> << n1 << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">" "</span> << n2 << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">" "</span> << n3 << endl;
}

<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 定义一个辅助函数</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">auto</span> addby1 = [] (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> x) -> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> 
{ 
    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cout</span> << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"addby1() called"</span> << endl;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> (x+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>); 
};

<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 嵌套的bind在使用外层bind()中的placeholders</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">auto</span> nested_f = bind(print, _1, bind(addby1, _1), _2); 

nested_f(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>);                 <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// addby1() called<cr> 1 2 3</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li></ul>

reference_wrapper<T>类型, 实现绑定引用

<code class="language-c++ hljs cpp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> x(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>);

<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 第二个参数使用引用x,第三个参数使用值x</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">auto</span> bind_ref = bind(print, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>::cref(x), x);  
bind_ref();                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 1 10 10; </span>

x = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>;

bind_ref();                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 1 100 10; 第二个参数跟着x变化了,第三个则没变</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>

bind与标准库协同工作

<code class="language-c++ hljs cpp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">RUN_GTEST(FunctorTest, BindPredefinedFunctors, @);

<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// all predefined functors:</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// negate, plus, minus, multiplies, divides, modulus, equal_to, </span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// not_equal_to, less, greater, less_equal, greater_equal,</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// logical_not, logical_and, logical_or, bit_and, bit_or, bit_xor</span>

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">auto</span> tenTimes = bind(multiplies<<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>>(), _1, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>);
EXPECT_EQ(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>, tenTimes(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>));
EXPECT_EQ(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">200</span>, tenTimes(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">20</span>));
EXPECT_EQ(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">300</span>, tenTimes(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">30</span>));

<span class="hljs-stl_container" style="box-sizing: border-box;"><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">vector</span><<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>></span> v{ <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">7</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">8</span> };
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// nested bind. output v[i] if 10*v[i] > 50.</span>
copy_if(v.begin(), v.end(),
    ostream_iterator<<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>>(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cout</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">", "</span>),
    bind(greater<<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>>(),
        bind(multiplies<<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>>(), _1, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>),
        <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">50</span>));                               <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 6,7,8,</span>
cr;

END_TEST;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li></ul>

bind与智能指针

<code class="language-c++ hljs cpp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">RUN_GTEST(FunctorTest, BindSmartPointer, @);

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> Temp 
{
    Temp(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> i=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) : i_(i) {}
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> print() { pln(i_); }
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> i_;
};

<span class="hljs-stl_container" style="box-sizing: border-box;"><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">vector</span><<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">shared_ptr</span><Temp></span>> vs =
{
    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">shared_ptr</span><Temp>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Temp(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>)),
    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">shared_ptr</span><Temp>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Temp(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>)),
    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">shared_ptr</span><Temp>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Temp(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>)),
};

for_each(vs.begin(), vs.end(), bind(&Temp::print, _1));  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 1<cr>2<cr>3<cr></span>

bind(&Temp::print, vs[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>])();        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 1</span>
bind(&Temp::print, vs[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>])();        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 2</span>
bind(&Temp::print, vs[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>])();        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 3</span>

END_TEST;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li></ul>

last but not least

bind中的参数是被copy或者是被move到目标函数的,除非显示指定按引用传递, 用std::ref 或者std::cref来包裹参数,否则是不会按引用来传递的。这意味着你要意识到, 在bind一个大的对象作为参数的时候可能存在的拷贝开销, 应该尽量用引用**

同时,因为move会改变对象的状态,因此,所以当你在bind参数列表里重用placeholders的时候,要考虑到参数已经被moved掉的情况, 标准建议:只有在参数是左值或者不可移动的右值的时候,重用placeholders才有意义。

源码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值