Почему компилятор не выбирает мою перегрузку функциональной функции в следующем примере?

StackOverflow https://stackoverflow.com/questions/1567834

Вопрос

Учитывая следующие шаблоны функций:

#include <vector>
#include <utility>

struct Base { };
struct Derived : Base { };

// #1
template <typename T1, typename T2>
void f(const T1& a, const T2& b)
{
};

// #2
template <typename T1, typename T2>
void f(const std::vector<std::pair<T1, T2> >& v, Base* p)
{
};

Почему следующий код всегда вызывает перегрузку № 1 вместо перегрузки № 2?

int main()
{
    std::vector<std::pair<int, int> > v;
    Derived derived;

    f(100, 200);  // clearly calls overload #1
    f(v, &derived);         // always calls overload #1

    return 0;
}

Учитывая, что второй параметр f является производным типом Base, Я надеялся, что компилятор выберет перегрузку № 2, так как это лучше, чем общий тип в перегрузке № 1.

Есть ли какие -либо методы, которые я мог бы использовать для переписывания этих функций, чтобы пользователь мог писать код, как показано в main Функция (т.е. использование компилятора-разъема типов аргументов)?

Это было полезно?

Решение

Вы можете сделать это:

f(v, static_cast<Base*>(&derived));

Или используйте Sfinae, чтобы удалить первую функцию в качестве кандидата от выбора:

// Install boost library and add these headers:
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits.hpp>

// #1 - change it to look like this (note the keyword void changed positions)
template <typename T1, typename T2>
typename boost::disable_if<
   typename boost::is_convertible<T2, Base*>, void>::type
f(const T1& a, const T2& b)
{
};

// #2 - this one can stay the same
template <typename T1, typename T2>
void f(const std::vector<std::pair<T1, T2> >& v, Base* p)
{
};

Другие советы

Учитывая, что второй параметр F является производным типом базы

Это кабриочрезируется такому, но это происходит*. Первая функция шаблона не требует конверсий, а вторая требует одного, поэтому она выбирает первое.

Это выбирает второе:

f(v, static_cast<Base*>(&derived));

В стороне, примечание, main возвращает int.

Помимо очевидных тем о Кениг Поиск это более или менее хорошо реализовано компиляторами (особенно старые довольно проблематичны), есть несколько ловушек относительно Специализация шаблона.

Специализация требует, чтобы типы точно соответствовали (не уверен, как STD определяет это, но, по моему опыту [GCC, MSVC], полученный класс не будет сопоставлен). Если вы добавите уродливый актер в базу*, он должен работать так, как вы собираетесь, добавьте еще одну специализацию для полученного ...

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top