Как компилятор C ++ решает, какая из этих функций вызывается? - PullRequest
1 голос
/ 18 августа 2011

Рассмотрим следующую настройку:

Мне дан интерфейс

template<class T>
  void FooClass<T>::foo(boost::function<double (int)> f)
{...}

Я хочу реализовать f с помощью Functor:

class MyFun {
    public: double operator()(int a) {do something...;}
}

Однако есть и другойфункция, определенная в интерфейсе

template<class T>
  template <class FunPtr> 
    void FooClass<T>::foo(const FunPtr& f)
{...}

Когда вызывается объект FooClass,

MyFun f;
FooClass<double> fooclass;
fooclass.foo(f);

он использует второе определение, а я хочу, чтобы оно вызывало первое - можно ли это изменитькак-то?

Ответы [ 2 ]

6 голосов
/ 18 августа 2011

Компилятор 'предпочитает' второе определение, поскольку версия шаблона *1003* дает точное совпадение для параметра объекта функции, тогда как параметр boost::function необходимо неявное преобразование , которое будет принято (и неявные преобразования считаются после разрешения прямой перегрузки). Вы можете достичь желаемого, просто создав объект boost::function и , а затем , передав его функции (обратите внимание, что вы можете сделать это в одной строке, я просто делаю это отдельно для ясности) :

boost::function<double (int)> bMyFun(myFunInstance);
fooClassInstance.foo(bMyFun);
2 голосов
/ 18 августа 2011

Вы можете явно создать объект boost::function, поэтому предпочтительной будет первая перегрузка:

fooclass.foo(boost::function<double (int)>(f));

Что касается названия вопроса, вам интересно, как работает разрешение перегрузки? Когда выбирается перегрузка, нетэмплированный тип лучше соответствует шаблонному, но шаблонный тип, который соответствует напрямую (FunPtr = MyFun), лучше, чем имплицитное преобразование (MyFun -> boost::function<double(int)>), поэтому вторая перегрузка лучше соответствует в вашем оригинальном случае.

(Спасибо @David за указание на явную ошибку в моей первоначальной формулировке!)

...