无法从std :: bind推断出std :: function的模板参数

acr*_*075 5 c++ templates variadic-templates c++11

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

这个包装函数是我尝试过的,但是例如对它的最后调用不会编译错误:

'bool Wrapper(Work*,std :: function <bool(Args ...)>,Args && ...)':无法推断'std :: function <bool的模板参数(double,std :: string, Args ...)>'from'std :: _ Bind <true,bool,std :: _ Pmf_wrap <bool(__ thiscall Work ::*)(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;
}
Run Code Online (Sandbox Code Playgroud)

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

我认为显式模板参数可以使模板解析成为可能.我究竟做错了什么?

Jar*_*d42 6

或 lambda的返回类型std::bind不是,并且从它们构造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;
}
Run Code Online (Sandbox Code Playgroud)

演示


Gar*_*365 5

在 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;
}
Run Code Online (Sandbox Code Playgroud)

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