В выводе аргумента шаблона, как функция sqrt‹T›(complex‹T›) соответствует вызову функции sqrt‹T›(‹T›)?

template<class T> T sqrt (T);
template<class T> complex<T> sqrt(complex<T>);
double sqrt(double);
void f(complex<double> z)
{
    sqrt(z);
}

Как в этом коде sqrt<double>(complex<double>) оказывается кандидатом на вывод аргумента шаблона? И автор говорит, что любой вызов, который соответствует sqrt<T>(complex<T>), также соответствует sqrt<T>(<T>). Как?

Код взят из Языка программирования C++ Бьярна Страуструпа. Раздел 13.3.2


person sajas    schedule 18.10.2012    source источник
comment
Вызов foo(something_concrete) соответствует вызову foo(anything), что для меня имеет смысл. Разумеется, из двух компилятор выберет более специализированный.   -  person SingerOfTheFall    schedule 18.10.2012


Ответы (1)


Ну, z относится к типу complex<double>. Поскольку T означает double, это явно соответствует

template <typename T> complex<T> sqrt(complex<T>);

Кроме того, если T равно complex<double>, это соответствует

template <typename T> T sqrt(T);

Где проблема с этим?

В результате сопоставления обеих этих функций набор перегрузки для принятия решения о том, какую из функций использовать, состоит из двух экземпляров

complex<double> sqrt<double>(complex<double>)
complex<double> sqrt<complex<double>>(complex<double>)

Оба совпадают, но первый является более специализированным и поэтому выбирается по разрешению перегрузки.

person Dietmar Kühl    schedule 18.10.2012