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