首页 > 解决方案 > 为什么这个重载的 std::function 参数不明确?

问题描述

我有下面的代码,其中一个类试图通过其构造函数获取两个 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)
     ^~~~~~~~~~

标签: c++overloading

解决方案


这个问题std::bindstd::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(); }

推荐阅读