无法从std::bind推导std::函数的模板参数

Could not deduce template argument for std::function from std::bind

本文关键字:std 参数 函数 bind 推导      更新时间:2023-10-16

我正试图找到一种方法来调用许多类成员函数,每个函数都有不同的参数,在调用前后都会发生某些已知的功能。

这个包装器函数是我尝试过的,但例如,对它的最后调用编译时没有出现错误:

'bool Wrapper(Work*,std::function<bool(Args…)>,Args&amp;…)':能够不推导的模板参数'std::函数<bool(double,std::string,Args…)>'from'std::_Bind<true,bool,std::_Pmf_wrap<bool(__thiscall工作::*)(double,std::string)、bool、Work、double、std::string>、Work*const>'

class Work
    {
    public:
        void DoWork(int a, double b, string c);
    private:
        void Pre() {};
        void Post() {};
        bool Step1() { return true; }
        bool Step2(int) { return true; }
        bool Step3(double, string) { return true; }
    };
template<typename... Args>
bool Wrapper(Work *work, std::function<bool(Args...)> func, Args&&... args)
    {
    work->Pre();
    bool ret = func(std::forward<Args>(args)...);
    work->Post();
    return ret;
    }
void Work::DoWork(int a, double b, string c)
{
    if (!Wrapper<>(this, std::bind(&Work::Step1, this))) // error
        return;
    if (!Wrapper<int>(this, std::bind(&Work::Step2, this), a)) // error
        return;
    if (!Wrapper<double, string>(this, std::bind(&Work::Step3, this), b, c)) // error
        return;
}
int main()
{
    Work work;
    work.DoWork(1, 2.0, "three");
    return 0;
}

(乍一看,将前置和后置功能放在步骤中似乎更可取,但这是不可取的,因为上面是实际代码的一个非常简化的示例,并且步骤有多个返回位置,没有测试。)

我认为明确的模板参数将使模板解析成为可能。我做错了什么?

返回的std::bind或lambda类型不是std::function,从它们构造哪个std::function将不明确。

一种解决方案是允许任何函子,而不使用std::function

template<typename F, typename... Args>
bool Wrapper(Work &work, F&& func, Args&&... args)
{
    work.Pre();
    const bool ret = std::forward<F>(func)(std::forward<Args>(args)...);
    work.Post();
    return ret;
}

演示

使用C++11,std::bind可以被lambda替换,并且可以删除包装器的模板:

class Work
{
    public:
        void DoWork(int a, double b, string c);
    private:
        void Pre() {};
        void Post() {};
        bool Step1() { return true; }
        bool Step2(int) { return true; }
        bool Step3(double, string) { return true; }
        friend bool Wrapper(Work *work, std::function<bool()> func);
};
bool Wrapper(Work *work, std::function<bool()> func)
{
    work->Pre();
    bool ret = func();
    work->Post();
    return ret;
}
void Work::DoWork(int a, double b, string c)
{
    if (!Wrapper(this, [this]() -> bool { return this->Step1(); }))
        return;
    if (!Wrapper(this, [this, a]() -> bool { return this->Step2(a); }))
        return;
    if (!Wrapper(this, [this, b, c]() -> bool { return this->Step3(b, c); }))
        return;
}
int main()
{
    Work work;
    work.DoWork(1, 2.0, "three");
    return 0;
}

示例:http://coliru.stacked-crooked.com/a/2cd3b3e2a4abfcdc