Ответ 1
По существу, правила частичного упорядочения говорят о том, что перегрузка dependent_type
более специализирована из-за этого не выводимого контекста.
Процесс упорядочения функций шаблонов основан на преобразовании типов функций шаблона и выполнении каждого из них поэтапного шаблона, переходя от первого шаблона (тот, который принимает T
) ко второму (тот, который принимает dependent_type
), затем от второго к первому.
Правила слишком сложны для репликации здесь, но прочитайте [temp.func.order]
и проходы, на которые он ссылается, если вы хотите узнать подробности, Здесь быстрое упрощение:
Для каждого параметра шаблона функции шаблона создайте уникальный тип и замените его параметром. Преобразованные типы для этого примера:
void foo(UniqueType); //ignoring the SFINAE for simplicity
void foo(typename dependent_type<UniqueType>::type);
Затем мы выполняем вывод шаблона в двух направлениях: один раз используя параметры первого шаблона в качестве аргументов для второго и один раз используя параметры второго в качестве аргументов для первого. Это похоже на выполнение вычета этих вызовов функций:
//performed against template <class T> void foo(typename dependent_type<T>::type);
foo(UniqueType{});
//performed against template <class T> void foo(T);
foo(dependent_type<UniqueType>::type{});
При выполнении этих вычетов мы пытаемся определить, является ли одна перегрузка более специализированной, а другая. Когда мы пытаемся выполнить первый, вывод не выполняется, поскольку typename dependent_type<T>::type
- это не выводимый контекст. Для второго вывод выводится успешно, потому что dependent_type<UniqueType>::type
является просто UniqueType
, поэтому T
выводится UniqueType
.
Поскольку вывод не прошел от второго шаблона к первому, второй шаблон считается более специализированным, чем первый. Конечным результатом является то, что разрешение перегрузки предпочитает второй шаблон для foo<int>(1)
.