问题描述
我正在阅读有关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
所以,关键是我传递了一个std::is_bind_expression<T>::value == true
的参数,并且修改了“正常”的std :: bind行为