Почему при выводе шаблона не выбрана правильная функция - PullRequest
4 голосов
/ 12 мая 2019

Я определил две функции перегрузки шаблона. Оба они принимают указатель на функцию в качестве аргумента. Разница в том, что в первом случае функция является членом класса, а во втором - нет.
Когда я пытаюсь передать функцию шаблона, класс функции, не являющийся членом, компилятор выбирает функцию шаблона, в которой функция является членом класса. В результате генерируется ошибка компилятора.

Ниже приведен код

#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 Ответ

3 голосов
/ 12 мая 2019

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)...));
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...