Как подстановка работает при выводе аргументов шаблона?

Стандарт C ++ 14.8.2 $ 7 гласит:

Подстановка происходит во всех типах и выражениях, которые используются в типе функции и в объявлениях параметров шаблона. Выражения включают в себя не только константные выражения, такие как те, которые появляются в границах массива или в качестве нетиповых аргументов шаблона, но также и общие выражения (то есть неконстантные выражения) внутри sizeof, decltypeи другие контексты, которые допускают непостоянные выражения. Замена происходит в лексическом порядке и останавливается, когда возникает условие, которое приводит к сбою дедукции. [Примечание: Эквивалентная замена в спецификациях исключений выполняется только тогда, когда создается спецификация исключений, и в этот момент программа плохо сформирована, если в результате замены получен недопустимый тип или выражение. — конец примечания]

Стандарт предоставляет пример здесь:

template <class T> struct A { using X = typename T::X; };
template <class T> typename T::X f(typename A<T>::X);
template <class T> void f(...) { }
template <class T> auto g(typename A<T>::X) -> typename T::X;
template <class T> void g(...) { }

void h() {
f<int>(0); // OK, substituting return type causes deduction to fail
g<int>(0); // error, substituting parameter type instantiates A<int>
}

Зачем звонить g<int>(0) здесь ошибка? Не тянется ли тип возврата T::X причина отказа замены? В чем разница между шаблонами функций f а также g?

6

Решение

Ключевые моменты, во-первых,

Замена происходит в лексическом порядке и останавливается, когда условие
что приводит к отказу дедукции встречается

И во-вторых, реализация A<int>определение вызывает серьезную ошибку, а не ошибку замещения, потому что это приводит к созданию плохо сформированной конструкции typename T::XT == int) вне непосредственного контекста. [Temp.deduct] / 8:

Только недопустимые типы и выражения в непосредственном контексте
Тип функции и типы параметров шаблона могут привести к
сбой удержания. [ Заметка: Оценка замещенных типов
и выражения могут привести к побочным эффектам, таким как создание экземпляров
специализации шаблона класса и / или шаблона функции
специализации, генерация неявно определенных функций и т. д.
Такие побочные эффекты не находятся в «непосредственном контексте» и могут привести к
программа плохо сформирована. — конечная нота ]

С шаблонами в вопросе, подставляя в typename T::X в типе функции приводит к ошибке вычета (т. е. SFINAE); подставляя в typename A<T>::X приводит к серьезной ошибке. Поскольку замена происходит в лексическом порядке, для template <class T> typename T::X f(typename A<T>::X); это заменяет в typename T::X во-первых, что приводит к ошибке вычета, и дальнейшая замена не предпринимается. За template <class T> auto g(typename A<T>::X) -> typename T::X;с другой стороны, он заменяет typename A<T>::X во-первых, что приводит к серьезной ошибке.

4

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]