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

时间:2016-05-12 07:03:59

标签: c++ templates c++11 variadic-templates

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

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

  

' bool Wrapper(Work *,std :: function< bool(Args ...)>,Args&& ...)' : 可以   不推断模板参数   '的std ::功能<布尔(双,的std :: string,参数数量...)>'从   '的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;
}

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

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

2 个答案:

答案 0 :(得分:4)

使用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

答案 1 :(得分:4)

返回的std::bind或lambda类型不是std::function,而std::functionstd::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; }

 NSLayoutConstraint *leftConstraint = [NSLayoutConstraint     constraintWithItem:self.view
                                                                  attribute:NSLayoutAttributeLeading
                                                                  relatedBy:0
                                                                     toItem:self.view
                                                                  attribute:NSLayoutAttributeLeading
                                                                 multiplier:1.0
                                                                   constant:0];
[self.view addConstraint:leftConstraint];

NSLayoutConstraint *rightConstraint = [NSLayoutConstraint constraintWithItem:self.view
                                                                   attribute:NSLayoutAttributeTrailing
                                                                   relatedBy:0
                                                                      toItem:self.view
                                                                   attribute:NSLayoutAttributeTrailing
                                                                  multiplier:1.0
                                                                    constant:0];
[self.view addConstraint:rightConstraint];

Demo