Re: вопрос о template instantiation
От: Николай Ивченков  
Дата: 09.11.09 15:42
Оценка: 2 (1)
KlugXP:

KXP>Вопрос: почему вызов F((A*)0, 0);

KXP>заставляет сгенериться класс S<V,A>?
KXP>Хотя функция
KXP>
template<typename T>
typename U<V, T>::x
F(T*, V*);

KXP>даже не вызывается и в для overload хуже чем
KXP>
template<typename T>
void F(T*, int)

KXP>(которая вызывается).

Разрешение перегрузки происходит после определения множества функций-кандидатов. В данном случае первоначальное множество кандидатов состоит из двух шаблонов функций, из которых, согласно 13.3.1/7, должна быть предпринята попытка сгенерировать специализации путём выведения шаблонных аргументов и их подстановки на место шаблонных параметров. То, что получится в итоге, и будет множеством функций-кандидатов, участвующих в разрешении перегрузки.

Для обоих шаблонов T выводится в A. В итоге получаются специализации объявлений (неявно инстанцированные — см. 14.7.1/8):

void F(A *, int); // [T = A]
U<V, A>::x F(A *, V *); // [T = A]


Конструкция U<V, A>::x требует существование определения для U<V, A>. Насколько я понимаю, по текущему стандарту, если бы определение U<V, A> отсутствовало, то программа была бы ill-formed (лишь в C++0x SFINAE действительно оправдывает своё название). Если определение присутствует, то компилятор в любом случае должен поинтересоваться, есть ли в U<V, A> член с именем x, и если есть, то является ли он типом. Если члена с именем x нет или если он есть, но это не тип, то дедукция типа считается неудачной, и, как следствие, специализация исключается из числа кандидатов (я откровенно не понимаю, зачем комитет по стандартизации C++ приплёл сюда дедукцию, а не просто указал на исключение функции из рассмотрения — как говорится, пути комитета неисповедимы). В данном случае тип x присутствует в U<V, A>, поэтому обе специализации включаются в множество функций-кандидатов. Дальнейшая судьба этих специализаций в ходе разрешения перегрузки никак не влияет на тот факт, что компилятору пришлось-таки инстанцировать U<V, A>. Функция U<V, A>::instantiate используется в программе (см. 3.2/2), поэтому требуется наличие в программе её определения и эта функция инстанцируется (см. 14.7.1/2). Она, в свою очередь, инстанцирует S<V, A>.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.