2014-01-31 3 views
1

У меня есть следующий код:C++ Функции перегрузки и шаблоны функций - другое поведение?

void A(const int*) 
{ 
    cout << "const int*" << endl; 
} 

void A(const int&) 
{ 
    cout << "const int&" << endl; 
} 

template <typename T> 
void B(const T*) 
{ 
    cout << "const T*" << endl; 
} 

template <typename T> 
void B(const T&) 
{ 
    cout << "const T&" << endl; 
} 

int main() 
{ 
    int* a = nullptr; 
    A(a);   //output: const int* 

    int* b = nullptr; 
    B(b);   //output: const T& 

    return 0; 
} 

A(a) в вызывающей функции A(const int*)
B(b) является вызовом функции ШАБЛОНА B(const T&)

Я не удивлен, от поведения шаблона из-за работы разрешения перегрузки в пути. Но я не могу объяснить, почему нетемпликационные функции возвращают противоположный результат (что более любопытно более интуитивно).

Это связано с тем, что с нетемплируемыми функциями нет необходимости выводить тип и считается точным совпадением (добавление константы разрешено?)?

Я не специалист по метапрограммированию и тому, что делает компилятор (например, разрешение перегрузки), и поэтому я немного смущен.

ответ

4

В вызове не шаблона вы передаете указатель на int. Итак, как он мог вызвать функцию, которая ожидает ссылку на int? Эти два совершенно разных типа. И да, добавление константы разрешено. Если вы были перегружены на constness, то:

void A(const int*) 
{ 
    cout << "const int*" << endl; 
} 

void A(int*) 
{ 
    cout << "int*" << endl; 
} 

Неконвертная версия будет выбрана как лучшее совпадение.

С шаблоном, все по-другому. Помните, что указатели тоже являются типами. Также справедливо выводить T как тип указателя. При вызове B(b), компилятор может использовать эту функцию:

template <typename T> 
void B(const T*) 
{ 
    cout << "const T*" << endl; 
} 

В этом случае T должен быть выведен в int и const T* становится const int*, указатель на константный междунар.

Или компилятор может выбрать эту функцию:

template <typename T> 
void B(const T&) 
{ 
    cout << "const T&" << endl; 
} 

В этом случае T выводится в int*. И const T& затем становится int* const&, то есть ссылкой на указатель const на int.

Так как во втором случае T сопоставляет то, что вы фактически передали (указатель на int), это лучшее совпадение.

+0

Он спрашивает, почему он звонит без шаблонов 'A' над шаблоном' A', а не почему он не называет 'B'. –

+0

@WilliamCustode: Нет, это не так. Нет шаблонов 'A'. –

+0

@WilliamCustode нет шаблона функции 'A'. – juanchopanza

0

Нет, поведение не отличается.

С B, T получает решение о int* и второй перегрузки-х

int* const& 

лучше подходит, чем первая перегрузка в

int const* 

Обратите внимание, что оба возможно, только первый из них лучше , Таким образом, в основном шаблон позволяет получить максимально допустимый доступ.

Для A существует только один вариант, так как указатель не конвертируется в ссылку, а это значит, что нужно удалить const.

Смежные вопросы