为什么这个重载的 std::function 参数不明确?
Why is this overloaded std::function parameter ambiguous?
我有下面的代码,其中 class 试图通过其构造函数获取两个 std::function 签名之一。我可以得到双参数的签名来编译,但是无参数的签名编译失败,说调用不明确。
#include <functional>
class Foo
{
public:
void baz(double value) {
}
};
class Bar
{
public:
void baz() {
}
};
class Overloader {
public:
Overloader(std::function<void(double)> inFuncWithArg)
: funcWithArg(inFuncWithArg)
{
}
Overloader(std::function<void(void)> inFuncNoArg)
: funcNoArg(inFuncNoArg)
{
}
private:
std::function<void(double)> funcWithArg;
std::function<void(void)> funcNoArg;
};
int main()
{
Foo foo;
Bar bar;
// Compiles
Overloader overloader1(std::bind(static_cast<void(Foo::*)(double)>(&Foo::baz)
, &foo, std::placeholders::_1));
// Fails to compile - "call of overloaded ‘Overloader(std::_Bind_helper::type)’ is ambiguous"
Overloader overloader2(std::bind(static_cast<void(Bar::*)(void)>(&Bar::baz)
, &bar));
return 0;
}
我错过了什么导致失败?另外,有没有更简单的方法来做到这一点?
这是完整的错误输出
main.cpp: In function ‘int main()’:
main.cpp:51:20: error: call of overloaded ‘Overloader(std::_Bind_helper::type)’ is ambiguous
, &bar));
^
main.cpp:32:5: note: candidate: Overloader::Overloader(std::function)
Overloader(std::function<void(void)> inFuncNoArg)
^~~~~~~~~~
main.cpp:27:5: note: candidate: Overloader::Overloader(std::function)
Overloader(std::function<void(double)> inFuncWithArg)
^~~~~~~~~~
这个问题更多的是关于 std::bind
而不是 std::function
。
表达式的结果
std::bind(&Foo::baz, &foo, std::placeholders::_1)
可以用一个 或更多 个参数调用,其中第一个参数可转换为双精度。
表达式的结果
std::bind(&Bar::baz, &bar)
可以使用零个 或更多 个参数调用,没有任何限制。
因此,第一个表达式只能初始化 std::function<void(double)>
,但第二个表达式可以初始化 std::function<void(double)>
或 std::function<void(void)>
,并且是不明确的。
真的,不要用std::bind
。如果有,可以使用 std::bind_front
。或者,使用 lambda。
std::bind_front
:
std::bind_front(&Foo::baz, &foo)
std::bind_front(&Bar::baz, &bar)
拉姆达:
[&foo](double) { foo.baz(value); }
[&bar] { bar.baz(); }
只需使用 lambda:
auto overloader1 = [&foo](double value) { foo.baz(value); };
auto overloader2 = [&bar]() { bar.baz(); }
我有下面的代码,其中 class 试图通过其构造函数获取两个 std::function 签名之一。我可以得到双参数的签名来编译,但是无参数的签名编译失败,说调用不明确。
#include <functional>
class Foo
{
public:
void baz(double value) {
}
};
class Bar
{
public:
void baz() {
}
};
class Overloader {
public:
Overloader(std::function<void(double)> inFuncWithArg)
: funcWithArg(inFuncWithArg)
{
}
Overloader(std::function<void(void)> inFuncNoArg)
: funcNoArg(inFuncNoArg)
{
}
private:
std::function<void(double)> funcWithArg;
std::function<void(void)> funcNoArg;
};
int main()
{
Foo foo;
Bar bar;
// Compiles
Overloader overloader1(std::bind(static_cast<void(Foo::*)(double)>(&Foo::baz)
, &foo, std::placeholders::_1));
// Fails to compile - "call of overloaded ‘Overloader(std::_Bind_helper::type)’ is ambiguous"
Overloader overloader2(std::bind(static_cast<void(Bar::*)(void)>(&Bar::baz)
, &bar));
return 0;
}
我错过了什么导致失败?另外,有没有更简单的方法来做到这一点?
这是完整的错误输出
main.cpp: In function ‘int main()’:
main.cpp:51:20: error: call of overloaded ‘Overloader(std::_Bind_helper::type)’ is ambiguous
, &bar));
^
main.cpp:32:5: note: candidate: Overloader::Overloader(std::function)
Overloader(std::function<void(void)> inFuncNoArg)
^~~~~~~~~~
main.cpp:27:5: note: candidate: Overloader::Overloader(std::function)
Overloader(std::function<void(double)> inFuncWithArg)
^~~~~~~~~~
这个问题更多的是关于 std::bind
而不是 std::function
。
表达式的结果
std::bind(&Foo::baz, &foo, std::placeholders::_1)
可以用一个 或更多 个参数调用,其中第一个参数可转换为双精度。
表达式的结果
std::bind(&Bar::baz, &bar)
可以使用零个 或更多 个参数调用,没有任何限制。
因此,第一个表达式只能初始化 std::function<void(double)>
,但第二个表达式可以初始化 std::function<void(double)>
或 std::function<void(void)>
,并且是不明确的。
真的,不要用std::bind
。如果有,可以使用 std::bind_front
。或者,使用 lambda。
std::bind_front
:
std::bind_front(&Foo::baz, &foo)
std::bind_front(&Bar::baz, &bar)
拉姆达:
[&foo](double) { foo.baz(value); }
[&bar] { bar.baz(); }
只需使用 lambda:
auto overloader1 = [&foo](double value) { foo.baz(value); };
auto overloader2 = [&bar]() { bar.baz(); }