Речь идет о том, что показывает пример.В итоге это те преобразования
- Параметр функции может быть
Base<T>
, а аргумент функции - Derived<T>
.Сравните с ifstream << "hello"
- таким образом выводится левая часть operator<<
. - Параметр функции может быть
const U&
, а аргумент функции - U
(то же самое для volatile). - Параметр функции может быть
const U*
или const E C::*
, а аргумент функции - U*
или E C::*
соответственно (это квалификационные преобразования) - то же самое для volatile.
Другие преобразования не могут быть выполнены для параметра / аргумента функции, которые участвуют в выводе.Весь диапазон преобразований может быть применен, если параметр функции не участвует в дедукции, но для этого нужен не выводимый контекст или контекст, где вообще нет аргумента для вывода, и реализация don 'на самом деле мы не согласны (см. здесь ).
Другими словами:
template<typename T> struct id { typedef T type; };
template<typename T> void f(T, typename id<T>::type);
int main() {
// deduction acts on void(int*, int*) - deduction does not need
// to deduce anything and follows [temp.arg.explicit]p4
f<int*>(0, 0);
// deduction acts on void(T, id<T>::type) - second is a non-deduced context,
// which *will* allow the conversion of int -> int*, since it will not compare
// the argument with parameter during deduction (since it is non-deduced).
f((int*)0, 0);
}
Второй пример жизненно важен для некоторого частичного упорядочения контексты для работы.