简体   繁体   English

std :: bind分配给std :: function

[英]std::bind assigned to std::function

I want a variable of type std::function<void(char**)> . 我想要一个类型为std::function<void(char**)>的变量。 Here's a simple example of failing to do that. 这是一个未能做到这一点的简单例子。

What I'm trying to understand is this: 我想要了解的是:

  • What is auto doing that the compiler doesn't complain when I call jj_2a(5, 6) ? 当我调用jj_2a(5, 6)时,编译器不会抱怨什么是自动执行? That function has all its parameters bound. 该函数的所有参数都绑定了。
  • But if I don't use auto, I get the behaviour I expect (compile error with arguments). 但是,如果我不使用auto,我会得到我期望的行为(使用参数编译错误)。 So clearly function<void(void)> is not at all what auto decided. 很明显, function<void(void)>根本不是汽车决定的。
  • If I bind the first argument and not the second ( jj_3 ), then calling with two arguments works (but drops the wrong argument, according to my mental model) while calling with one argument (which I think should work) doesn't compile. 如果我绑定第一个参数而不是第二个参数( jj_3 ),那么使用两个参数调用(但根据我的心理模型删除错误的参数),而使用一个参数调用(我认为应该工作)不会编译。
  • Using std::functional for jj_3_f says "no viable conversion", though the error message isn't so far helping me. 使用std::functional for jj_3_f说“没有可行的转换”,虽然错误信息对我没有帮助。

See below for compiler and specific errors. 请参阅下面的编译器和特定错误。 This is linux, clang 3.8.0, ubuntu 16.04.1. 这是linux,clang 3.8.0,ubuntu 16.04.1。

#include <functional>
#include <iostream>

void jj_1(int x, int y) { std::cout << x << ' ' << y << std::endl; }

int main() {
  using namespace std::placeholders; // for _1, _2, _3...

  auto jj_2a = std::bind(jj_1, 3, 2);
  jj_2a(5, 6);  // This works, prints "3 2", no compiler warning, is auto drunk?
  jj_2a();      // This also works, prints "3 2".
  std::function<void(void)> jj_2a_f = std::bind(jj_1, 30, 20);
  //jj_2a_f(50, 60);  // Compile error, good!
  jj_2a_f();  // This works, prints "30 20", good!

  auto jj_2b = std::bind(jj_1, _2, _1);
  jj_2b(5, 6);  // This works, prints "6 5", good.

  auto jj_3 = std::bind(jj_1, 3, _2);
  jj_3(5, 6);  // This works, prints "3 6", so it's the first arg that is dropped!
  //jj_3(7);     // Compile error!

  //std::function<void(int)> jj_3_f = std::bind(jj_1, 3, _2);  // Compile error, no viable conversion!
  //jj_4(11);
}

I compile this with 我用它编译

clang++  -std=c++14 -Wall -Wextra /tmp/foo.cc -o /tmp/foo

The compiler warnings associated with jj_3(7) are these: jj_3(7)相关的编译器警告jj_3(7)

/tmp/foo.cc:21:7: error: no matching function for call to object of type 'std::_Bind<void (*(int,
  std::_Placeholder<2>))(int, int)>'
  jj_3(7);     // Compile error!
  ^~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/functional:1129:2: note: 
  candidate template ignored: substitution failure [with _Args = <int>]: no viable conversion from
  'std::_No_tuple_element' to 'int'
    operator()(_Args&&... __args)
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/functional:1143:2: note: 
  candidate template ignored: substitution failure [with _Args = <int>]: no viable conversion from
  'std::_No_tuple_element' to 'int'
    operator()(_Args&&... __args) const
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/functional:1157:2: note: 
  candidate template ignored: substitution failure [with _Args = <int>]: no viable conversion from
  'std::_No_tuple_element' to 'int'
    operator()(_Args&&... __args) volatile
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/functional:1171:2: note: 
  candidate template ignored: substitution failure [with _Args = <int>]: no viable conversion from
  'std::_No_tuple_element' to 'int'
    operator()(_Args&&... __args) const volatile
    ^
1 error generated.

The compiler warnings associated with jj_3_f are these: jj_3_f相关的编译器警告jj_3_f

/tmp/foo.cc:23:32: error: no viable conversion from 'typename _Bind_helper<__is_socketlike<void (&)(int,
  int)>::value, void (&)(int, int), int, const _Placeholder<2> &>::type' (aka '_Bind<void (*(int,
  std::_Placeholder<2>))(int, int)>') to 'std::function<void (int)>'
  std::function<void(int)> jj_3_f = std::bind(jj_1, 3, _2);  // Compile error, no viable conversion!
               ^        ~~~~~~~~~~~~~~~~~~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/functional:2008:7: note: 
  candidate constructor not viable: no known conversion from 'typename
  _Bind_helper<__is_socketlike<void (&)(int, int)>::value, void (&)(int, int), int, const
  _Placeholder<2> &>::type' (aka '_Bind<void (*(int, std::_Placeholder<2>))(int, int)>') to
  'nullptr_t' for 1st argument
  function(nullptr_t) noexcept
  ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/functional:2019:7: note: 
  candidate constructor not viable: no known conversion from 'typename
  _Bind_helper<__is_socketlike<void (&)(int, int)>::value, void (&)(int, int), int, const
  _Placeholder<2> &>::type' (aka '_Bind<void (*(int, std::_Placeholder<2>))(int, int)>') to 'const
  std::function<void (int)> &' for 1st argument
  function(const function& __x);
  ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/functional:2028:7: note: 
  candidate constructor not viable: no known conversion from 'typename
  _Bind_helper<__is_socketlike<void (&)(int, int)>::value, void (&)(int, int), int, const
  _Placeholder<2> &>::type' (aka '_Bind<void (*(int, std::_Placeholder<2>))(int, int)>') to
  'std::function<void (int)> &&' for 1st argument
  function(function&& __x) : _Function_base()
  ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/functional:2054:2: note: 
  candidate template ignored: substitution failure [with _Functor = std::_Bind<void (*(int,
  std::_Placeholder<2>))(int, int)>, $1 = void]: no type named 'type' in
  'std::result_of<std::_Bind<void (*(int, std::_Placeholder<2>))(int, int)> (int)>'
    function(_Functor);
    ^
1 error generated.

Fwiw, the thing I really want to do is parallel. Fwiw,我真正想要的是平行。 I have a function 我有一个功能

void MyFunction(A& a, B& b, const char** thing);

where A and B are class names. 其中AB是类名。 I have another function that expects a callback thus: 我有另一个期望回调的函数:

C DoStuff(const std::string& s, std::function<void(const char** thing)> f);

which I then try to call 然后我试着打电话

DoStuff("Hello!", std::bind(MyFunction, an_a, a_b, _3));

and I get errors about no viable conversion. 并且我得到关于没有可行转换的错误。

Note: this answer assumes that you have read Why do objects returned from bind ignore extra arguments? 注意:这个答案假定你已经读过为什么从bind返回的对象会忽略额外的参数?

The object returned by std::bind is not a std::function ; std::bind返回的对象不是std::function ; it is an object of an unspecified type that differs from std::function in a number of ways; 它是一个未指定类型的对象,它在很多方面与std::function不同; most importantly for your case, it ignores any extra arguments passed to it. 最重要的是,它会忽略传递给它的任何额外参数。

If you use placeholders up to _2 (for example) in your bind expression, the returned object can be called with any number of arguments as long as that number is at least 2. 如果在绑定表达式中使用最多_2 (例如)的占位符,则只要该数字至少为2,就可以使用任意数量的参数调用返回的对象。

  • What is auto doing that the compiler doesn't complain when I call jj_2a(5, 6)? 当我调用jj_2a(5,6)时,编译器不会抱怨什么是自动执行? That function has all its parameters bound. 该函数的所有参数都绑定了。

You are passing extra arguments; 你正在传递额外的论点; those extra arguments are ignored. 那些额外的论点被忽略了。

  • But if I don't use auto, I get the behaviour I expect (compile error with arguments). 但是,如果我不使用auto,我会得到我期望的行为(使用参数编译错误)。 So clearly function is not at all what auto decided. 所以显然功能根本不是汽车决定的。

Correct; 正确; bind does not return a std::function , it returns a callable object of unspecified type that can (depending on signature) be used to construct a std::function . bind不返回std::function ,它返回一个未指定类型的可调用对象,可以(取决于签名)用于构造std::function

  • If I bind the first argument and not the second (jj_3), then calling with two arguments works (but drops the wrong argument, according to my mental model) while calling with one argument (which I think should work) doesn't compile. 如果我绑定第一个参数而不是第二个参数(jj_3),那么使用两个参数调用(但根据我的心理模型删除错误的参数),而使用一个参数调用(我认为应该工作)不会编译。

If you use std::placeholders::_2 , you must pass at least 2 arguments. 如果使用std::placeholders::_2 ,则必须至少传递2个参数。 std::placeholders::_2 picks the second argument passed to the object returned from bind . std::placeholders::_2选择传递给bind返回的对象的第二个参数。

  • Using std::functional for jj_3_f says "no viable conversion", though the error message isn't so far helping me. 使用std :: functional for jj_3_f说“没有可行的转换”,虽然错误信息对我没有帮助。

If you use std::placeholders::_2 , you must pass at least 2 arguments; 如果使用std::placeholders::_2 ,则必须传递至少2个参数; the constructor of std::function checks this. std::function的构造std::function检查这个。

This wont compile: 这不会编译:

 jj_3(7);     // Compile error!

because you said earlier that jj_3 binds second parameter to the second argument at the call place. 因为你之前说过jj_3将第二个参数绑定到调用位置的第二个参数。 So without chaning it, you would have to call: 所以没有chaning它,你将不得不打电话:

 jj_3(0, 7); // 0 is notused

or rather change your jj_3 declaration to: 或者更改你的jj_3声明:

 auto jj_3 = std::bind(jj_1, 3, _1);

This: 这个:

 std::function<void(int)> jj_3_f = std::bind(jj_1, 3, _2);  // Compile error, no viable conversion!

does not compile because you should have: 不编译,因为你应该有:

 std::function<void(int, int)> jj_3_f

as I said above, if you use place holder _2 then you want your jj_3_f to ba called with two parameters. 如上所述,如果您使用占位符_2,那么您希望使用两个参数调用jj_3_f。

In the line 在线

std::function<void(int)> jj_3_f = std::bind(jj_1, 3, _2);  // Compile error, no viable conversion!

You need to replace by 你需要替换

std::function<void(int,int)> jj_3_f = std::bind(jj_1, 3, _2);

Or by 或者

std::function<void(int,int)> jj_3_f = std::bind(jj_1, 3, _2);

Line: 线:

 auto jj_3 = std::bind(jj_1, 3, _2);

You need to replace by 你需要替换

auto jj_3 = std::bind(jj_1, 3, _1);

You need only one args so you should write _1 你只需要一个args,所以你应该写_1

Replace: 更换:

//std::function<void(int)> jj_3_f = std::bind(jj_1, 3, _2);  // Compile error, no viable conversion!
//jj_4(11);

with: 有:

std::function<void(int)> jj_3_f = std::bind(jj_1, 3, _1);
jj_3_f(5);

The placeholder is the number of the parameter in the result function (one argument, then the first placeholder), not the parameter in the " binded " function. 占位符是结果函数中的参数编号(一个参数,然后是第一个占位符),而不是“ 绑定 ”函数中的参数。

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

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