![](/img/trans.png)
[英]Why std::bind can be assigned to argument-mismatched std::function?
[英]std::bind assigned to std::function
我想要一个类型为std::function<void(char**)>
的变量。 这是一个未能做到这一点的简单例子。
我想要了解的是:
jj_2a(5, 6)
时,编译器不会抱怨什么是自动执行? 该函数的所有参数都绑定了。 function<void(void)>
根本不是汽车决定的。 jj_3
),那么使用两个参数调用(但根据我的心理模型删除错误的参数),而使用一个参数调用(我认为应该工作)不会编译。 std::functional
for jj_3_f
说“没有可行的转换”,虽然错误信息对我没有帮助。 请参阅下面的编译器和特定错误。 这是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);
}
我用它编译
clang++ -std=c++14 -Wall -Wextra /tmp/foo.cc -o /tmp/foo
与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.
与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,我真正想要的是平行。 我有一个功能
void MyFunction(A& a, B& b, const char** thing);
其中A
和B
是类名。 我有另一个期望回调的函数:
C DoStuff(const std::string& s, std::function<void(const char** thing)> f);
然后我试着打电话
DoStuff("Hello!", std::bind(MyFunction, an_a, a_b, _3));
并且我得到关于没有可行转换的错误。
注意:这个答案假定你已经读过为什么从bind返回的对象会忽略额外的参数?
std::bind
返回的对象不是std::function
; 它是一个未指定类型的对象,它在很多方面与std::function
不同; 最重要的是,它会忽略传递给它的任何额外参数。
如果在绑定表达式中使用最多_2
(例如)的占位符,则只要该数字至少为2,就可以使用任意数量的参数调用返回的对象。
- 当我调用jj_2a(5,6)时,编译器不会抱怨什么是自动执行? 该函数的所有参数都绑定了。
你正在传递额外的论点; 那些额外的论点被忽略了。
- 但是,如果我不使用auto,我会得到我期望的行为(使用参数编译错误)。 所以显然功能根本不是汽车决定的。
正确; bind
不返回std::function
,它返回一个未指定类型的可调用对象,可以(取决于签名)用于构造std::function
。
- 如果我绑定第一个参数而不是第二个参数(jj_3),那么使用两个参数调用(但根据我的心理模型删除错误的参数),而使用一个参数调用(我认为应该工作)不会编译。
如果使用std::placeholders::_2
,则必须至少传递2个参数。 std::placeholders::_2
选择传递给bind
返回的对象的第二个参数。
- 使用std :: functional for jj_3_f说“没有可行的转换”,虽然错误信息对我没有帮助。
如果使用std::placeholders::_2
,则必须传递至少2个参数; std::function
的构造std::function
检查这个。
这不会编译:
jj_3(7); // Compile error!
因为你之前说过jj_3将第二个参数绑定到调用位置的第二个参数。 所以没有chaning它,你将不得不打电话:
jj_3(0, 7); // 0 is notused
或者更改你的jj_3声明:
auto jj_3 = std::bind(jj_1, 3, _1);
这个:
std::function<void(int)> jj_3_f = std::bind(jj_1, 3, _2); // Compile error, no viable conversion!
不编译,因为你应该有:
std::function<void(int, int)> jj_3_f
如上所述,如果您使用占位符_2,那么您希望使用两个参数调用jj_3_f。
在线
std::function<void(int)> jj_3_f = std::bind(jj_1, 3, _2); // Compile error, no viable conversion!
你需要替换
std::function<void(int,int)> jj_3_f = std::bind(jj_1, 3, _2);
或者
std::function<void(int,int)> jj_3_f = std::bind(jj_1, 3, _2);
线:
auto jj_3 = std::bind(jj_1, 3, _2);
你需要替换
auto jj_3 = std::bind(jj_1, 3, _1);
你只需要一个args,所以你应该写_1
更换:
//std::function<void(int)> jj_3_f = std::bind(jj_1, 3, _2); // Compile error, no viable conversion!
//jj_4(11);
有:
std::function<void(int)> jj_3_f = std::bind(jj_1, 3, _1);
jj_3_f(5);
占位符是结果函数中的参数编号(一个参数,然后是第一个占位符),而不是“ 绑定 ”函数中的参数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.