Ответ 1
(Я ожидал, что Альф Штайнбах опубликует ответ, но поскольку он этого не делает, я отправлю ссылку, которую он упомянул в чате Lounge С++):
Стандарт указывает, что экземпляры шаблонов выполняются после того, как единица перевода уже была переведена, так что вовремя экземпляры шаблонов происходят после того, как все незатемные элементы уже обработаны. Это описано в разделе 2.2 Фазы перевода:
Пункты 1-6 определяют работу препроцессора и основные текстовые операции (преобразования набора символов, конкатенация литералов...)
7/Символы белого пробела, разделяющие токены, уже не являются значимыми. Каждый токен предварительной обработки преобразуется в токен. (2.7). Результирующие маркеры синтаксически и семантически анализируются и переводятся как единица перевода.
8/Переводные единицы перевода и единицы экземпляра объединяются следующим образом: каждая переведенная единица перевода исследуется для создания списка необходимых экземпляров. Определены требуемые шаблоны. Определяется реализация, требуется ли источник блоков перевода, содержащих эти определения. Все необходимые экземпляры выполняются для создания единиц экземпляра. [Примечание: они похожи на переведенные единицы перевода, но не содержат ссылок на неинсталлированные шаблоны и определения шаблонов. - конец примечания] Программа плохо сформирована, если какая-либо инстанция не удалась.
Я сократил некоторые примечания для краткости. Теперь важный бит, кажется, заключается в том, что код переведен без запуска экземпляров шаблонов за один шаг, а затем на более позднем этапе создаются шаблоны. Это, в свою очередь, означает, что если тип завершен в любом месте единицы перевода, он будет обработан к тому времени, когда компилятор достигнет экземпляра.
Отказ от ответственности: это кажется хорошей причиной для всех компиляторов, которые я пробовал, демонстрируя то же самое поведение (gcc, clang, goau, VS 2010), но это только указывает, когда со временем выполняется инстанцирование, явно не указывают, что тип может быть неполным в момент создания шаблона.