简体   繁体   English

std :: bind和std :: function问题

[英]std::bind and std::function questions

int func(int x){return x;}
...
std::function<int(int)> x = std::bind(func, std::placeholders::_1);
x(123);
  1. Does x(123) actually call the operator() of the functor which std::function generated which in turn calls the operator() of the functor which std::bind generated which finally calls func ? x(123)实际上是否调用了生成std::function的functor的operator() ,而后者又调用了最终调用func std::bind生成的functor的operator() Does this get optimized into something as optimal as calling func(123) ? 这是否被优化为与调用func(123)一样最优的东西?
  2. Where does the functor live which std::bind generates? 构造函数在哪里生成std::bind生成的? In what scope? 在什么范围? And how does std::bind name it? std::bind如何命名呢? (can there be name collisions) (可以有名称冲突)
  3. Can lambdas replace all uses of std::bind ? lambda可以替换std::bind所有用法吗?
  4. Is std::bind as optimal as implementing it as a lambda instead? std::bind是否最适合将其作为lambda实现?
  5. What's up with the syntax of the template argument of std::function ? 怎么了std::function的模板参数的语法? How does that get parsed and how can I use that template argument syntax elsewhere? 如何解析它以及如何在其他地方使用该模板参数语法?

Does x(123) actually call the operator() of the functor which std::function generated which in turn calls the operator() of the functor which std::bind generated which finally calls func? x(123)实际上是否调用了生成std :: function的functor的operator(),而后者又调用了最终调用func的std :: bind生成的functor的operator()? Does this get optimized into something as optimal as calling func(123)? 这是否被优化为与调用func(123)一样最优的东西?

I wouldn't describe the operator() of std::function as 'generated' (it's a regular member), but otherwise that is a good description. 我不会将std::functionoperator()描述为'generated'(它是常规成员),但除此之外这是一个很好的描述。 Optimizations are up to your compiler, but be warned that to optimize the indirection of std::function (which requires the use of type erasure) a compiler may need to perform heroics. 优化取决于您的编译器,但要注意优化std::function的间接(需要使用类型擦除),编译器可能需要执行英雄。

Where does the functor live which std::bind generates? 构造函数在哪里生成std :: bind生成的? In what scope? 在什么范围? And how does std::bind name it? std :: bind如何命名呢? (can there be name collisions) (可以有名称冲突)

The call to std::bind returns a functor of unspecified type, and a copy of that functor is stored inside the x object. std::bind的调用返回一个未指定类型的仿函数,该仿函数的副本存储在x对象中。 This copy will live as long as x itself. 此副本将与x本身一样长。 There is no name involved so I'm not sure what you mean by that. 没有名字涉及,所以我不确定你的意思。

Can lambdas replace all uses of std::bind? lambda可以替换std :: bind的所有用法吗?

No. Consider auto bound = std::bind(functor, _1); 不。考虑auto bound = std::bind(functor, _1); where functor is a type with an overloaded operator() , let's say on long and int . functor是一个带有重载operator()的类型,让我们说longint Then bound(0L) doesn't have the same effect as bound(0) and you can't replicate that with a lambda. 然后bound(0L)bound(0)没有相同的效果,你不能用lambda复制它。

Is std::bind as optimal as implementing it as a lambda instead? std :: bind是否最适合将其作为lambda实现?

This is up to the compiler. 这取决于编译器。 Measure yourself. 衡量自己。

What's up with the syntax of the template argument of std::function? 怎么了std :: function的模板参数的语法? How does that get parsed and how can I use that template argument syntax elsewhere? 如何解析它以及如何在其他地方使用该模板参数语法?

It's a function type. 这是一种功能类型。 Perhaps you're already familiar with the syntax for pointers/references to functions: void(*)() , int(&)(double) . 也许您已经熟悉指针/函数引用的语法: void(*)()int(&)(double) Then just remove the pointer/reference out of the type, and you just have a function type: void() , int(double) . 然后只需删除类型中的指针/引用,您只需要一个函数类型: void()int(double) You can use those like so: 你可以使用这样的:

typedef int* function_type(long);
function_type* p; // pointer to function

1 . 1。 Does x(123) actually call the operator() of the functor which std::function generated which in turn calls the operator() of the functor which std::bind generated which finally calls func ? x(123)实际上是否调用了生成std::function的functor的operator() ,而后者又调用了最终调用func std::bind生成的functor的operator() Does this get optimized into something as optimal as calling func(123) ? 这是否被优化为与调用func(123)一样最优的东西?

If you have optimizations enabled, the 'stuff' gets inlined and you can count on this being as optimal as calling func(123) . 如果你启用了优化,那么'stuff'就会被内联,你可以指望它与调用func(123)一样最优。

2 . 2。 Where does the functor live which std::bind generates? 构造函数在哪里生成std::bind生成的? In what scope? 在什么范围? And how does std::bind name it? std::bind如何命名呢? (can there be name collisions) (可以有名称冲突)

Precising: bind generates a 'fleeting', implementation defined, bind expression, that is assignable to function<> . 精确: bind生成“转瞬即逝”,实现定义,绑定表达式,可分配给function<> Function is just a class template (Thanks, Luc T.). 功能只是一个类模板(谢谢,Luc T.)。 And it lives in the standard library. 它存在于标准库中。 However, the bind expressions are implementation defined. 但是,绑定表达式是实现定义的。

The standard library does come with traits ( std::is_bind_expression<> ) to allow MPL detection of such expressions. 标准库附带的性状( std::is_bind_expression<>以允许这样的表达式的MPL检测。 One decisive feature of bind expressions over std::function is that they are (what I'd call) deferred callable objects (ie that they retain full call site semantics including the ability to select overloads at the actual application site). 绑定表达式在std :: function上的一个决定性特征是它们(我称之为) 延迟可调用对象 (即它们保留完整的调用站点语义,包括在实际应用程序站点选择重载的能力)。 std::function<> , on the other hand, commits to a single prototype and internally stores the callable object by type erasure ( think variant or any ). 另一方面, std::function<>提交单个原型并通过类型擦除( 想象variantany )在内部存储可调用对象

3 . 3。 Can lambdas replace all uses of std::bind? lambda可以替换std :: bind的所有用法吗?

4 . 4。 Is std::bind as optimal as implementing it as a lambda instead? std :: bind是否最适合将其作为lambda实现?

AFAICT lambdas should compile down to about the same as the bind expressions. AFAICT lambdas应该编译为与绑定表达式大致相同。 One thing that I think lambdas can't do that bind expressions can is nested bind expressions Edit While the specific idiom of nested bind expressions is not replicatable using lambdas, lambdas are of course able to express (nearly) the same much more naturally: 有一件事我认为 lambdas不能做那个绑定表达式可以nested bind expressions 编辑虽然nested bind expressions的特定习惯用法不能使用lambdas复制,但lambdas当然能够更自然地表达(几乎)相同的内容:

 bind(f, bind(g, _1))(x); 
 // vs.
 [](int x) { f(g(x)); };

5 . 5。 What's up with the syntax of the template argument of std::function ? 怎么了std::function的模板参数的语法? How does that get parsed and how can I use that template argument syntax elsewhere? 如何解析它以及如何在其他地方使用该模板参数语法?

It is just a function signature (the type of a function), being passed as template parameter. 它只是一个函数签名(函数的类型 ),作为模板参数传递。

You can also use it as a function parameter type, which degrades to a function pointer(similar to how array by-value parameters degrade to pointers, Thanks David!). 您还可以将它用作函数参数类型,它会降级为函数指针(类似于数组按值参数降级为指针的方式,感谢David!)。 In practice, most anywhere, as long as you don't have a need to name a variable/type: 在实践中,大多数地方,只要您不需要命名变量/类型:

 void receiveFunction(void(int, double)); // spunky 'function<>'-style syntax

 void sample(int, double) { } 

 int main()
 { 
     receiveFunction(sample);
 }

 void receiveFunction(void (*f)(int, double)) // boring 'old' style syntax
 //                   void ( f)(int, double)  // ... also ok
 {
     // ..
 }

Can lambdas replace all uses of std::bind? lambda可以替换std :: bind的所有用法吗?

C++14 will allow lambdas to mostly replace bind. C ++ 14将允许lambdas主要替换bind。 Responding in particular to Luc Danton's answer, in C++14, you can write templated lambdas using auto such that bound(0) and bound(0L) behave differently. 特别回应Luc Danton的回答,在C ++ 14中,你可以使用auto编写模板化的lambda,使得bound(0)bound(0L)表现不同。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM