为什么在模板推导过程中未选择正确的功能

时间:2019-05-12 13:38:37

标签: c++ templates

我定义了两个重载模板函数。他们两个都以函数指针作为参数。区别在于,第一个函数是类的成员,而第二个函数不是。
当我尝试传递非成员函数类的模板函数时,编译器会选择该函数为类成员的模板函数。 结果生成了编译器错误。

下面是代码

#include <type_traits>
#include <iostream>
#include <deque>
#include <thread>
#include <functional>

class Worker
{
public:
    Worker()
    {


    }
template<typename _Callable, typename Object, typename... _Args>
    void QueueFunction(_Callable __f, Object   obj, _Args... __args)
    {
           funcs.emplace_back([=]()mutable
                    {
                         (obj.*__f)(__args...);
                    });
           std::cout << "size::" <<funcs.size()<<std::endl;
           std::cout << funcs.empty()<<std::endl;
    }
    template<typename _Callable, typename... _Args>
    void QueueFunction(_Callable __f, _Args... __args)
    {

               funcs.emplace_back([=]()mutable
                        {
                             (*__f)(__args...);
                        });
    }
    std::deque<std::function<void()>> funcs;

};
void sub(int x ,int y)
{
               std::cout << "sub::result: " << x-y << std::endl;
}

int main()
{
    Worker w;
    w.QueueFunction(&sub,5,6);
}

我希望可以选择以下功能

template<typename _Callable, typename... _Args>
void QueueFunction(_Callable __f, _Args... __args)

1 个答案:

答案 0 :(得分:3)

SFINAE不查看函数的主体,仅考虑其声明。

这意味着当我们谈论重载解决方案时,您的类如下所示:

class Worker
{
  template<typename A, typename B, typename... Cs>
  void QueueFunction(A a, B b, Cs... cs)
  {}

  template<typename A, typename Bs>
  void QueueFunction(A a, Bs... bs)
  {}
};

考虑到这一点,将w.QueueFunction(&sub,5,6);与第一个绑定更牢固是很有意义的。

编辑:您所做的基本上是在重新发明std::bind,所以您最好使用它。它将同时平滑处理函子,成员函数以及所有其他内容。

template<typename... Args>
void QueueFunction(Args&&... args) {
    funcs.emplace_back(std::bind(std::forward<Args>(args)...));
}