具有std :: bind的功能组合

问题描述

我正在阅读有关C ++ 11 STL的 Nicolai Josuttis 精美书籍的第二版。

我找到了以下代码

#include <functional>
#include <iostream>

int main()
{
   auto plus10 = std::bind(std::plus<int>(),std::placeholders::_1,10);
   std::cout << "+10:    " << plus10(7) << std::endl;

   auto plus10times2 = std::bind(std::multiplies<int>(),std::bind(std::plus<int>(),10),2);
   // ...
}

我无法理解绑定对象“ plus10times2”的工作方式。 它不应该绑定到int参数吗?

如何绑定另一个绑定对象?

调用plus10times2调用运算符(例如,像plus10times2(7))时如何工作?

解决方法

它称为nested binding (i.e. std::bind)。一个std::bind呼叫有一个或多个std::bind

在这种情况下,它的工作方式如下:

首先,调用嵌套的std::bind表达式,这意味着

std::bind(std::plus<int>(),std::placeholders::_1,10) 

,第一个参数为plus10times2,然后传递给外部参数: 即

std::bind(std::multiplies<int>(),/* result of nested bind */,2);

由于嵌套的绑定表达式(即内部std::bind(std::plus<int>() ...)返回一个int eger,而外部的表达式(即std::bind(std::multiplies<int>()...)在该位置期望一个int ger,效果很好。

更多阅读内容:Nested bind expressions


话虽如此,从C ++ 11开始,我们还有lambda function。在lambda调用中将嵌套的bind表达式写为等于可能会清除以下内容:

const auto plus10_lmda = [](int arg) { return std::plus{}(arg,10); };
const auto plus10times2_lmda = [](auto callblePlus,int innerArg) { return std::multiplies{}(callblePlus(innerArg),2); };
std::cout << plus10times2_lmda(plus10_lmda,7);   // prints 34

或完全嵌套并立即调用内部lambda

const auto plus10times2_lmda = [](int innerArg) { 
   return std::multiplies{}(
      [](int arg) { return std::plus{}(arg,10); }(innerArg) // invoke the inner one immediately,2); 
};
std::cout << plus10times2_lmda(7);  // prints 34
,

从cppreference.com摘录的有关std :: bind:

”给出一个从先前的绑定获得的对象g,当在函数调用表达式g(u1,u2,... uM)中调用该对象时,将对存储的对象进行调用,就像通过std :: invoke(fd,std :: forward(v1),std :: forward(v2),...,std :: forward(vN)),其中fd是std :: decay_t类型的值绑定参数v1,v2,...,vN的确定如下确定。

...

如果存储的参数arg的类型为std :: is_bind_expression :: value == true的T类型(例如,另一个绑定表达式直接传递到了绑定的初始调用中),则bind执行函数组合:传递bind子表达式将返回的函数对象,该子表达式将被急切地调用,并将其返回值传递给外部可调用对象。如果bind子表达式具有任何占位符参数,则它们与外部绑定共享(从u1,u2,...中挑选)。具体来说,上述std :: invoke调用中的参数vn为arg(std :: forward(uj)...),而同一调用中的Vn类型为std :: result_of_t &&(简历资格与g相同)。

所以,关键是我传递了一个std::is_bind_expression<T>::value == true的参数,并且修改了“正常”的std :: bind行为