Если я правильно прочитал стандарт, я не верю, что ваш код неверен (за исключением использования идентификатора _T
). Пробежать лишнюю милю - это фантастика, но GCC не ошибается, принимая это как есть.
Причина в том, что ваша программа содержит только неявную реализацию вашего шаблона. Согласно N1905 1 (выделено мое):
14.7.1 Неявная реализация [temp.inst]
1 ... Неявное создание экземпляра класса
специализация шаблона вызывает неявную реализацию
объявления , но не определений или аргументов по умолчанию
функции-члены класса, классы-члены , члены-статические данные и член
шаблоны; и это вызывает неявную реализацию определений
член анонимных союзов. Если только член шаблона класса или
шаблон члена был явно создан или явно
специализация, специализация члена неявно
создается, когда на специализацию ссылаются в контексте,
требует, чтобы определение члена существовало; в частности,
инициализация (и любые связанные побочные эффекты) статических данных
член не происходит, если статический член данных сам не используется в
способ, который требует определения статического члена данных.
Ничего использует object_creator
так, чтобы его определение существовало. Как таковая только декларация когда-либо проверяется. Кроме того, требуется создать только само объявление class ObjectCreator
, а не его определение (или определение его конструктора). По этой же причине можно определить переменную extern типа класса, объявленного вперед:
extern class C c;
Приведенный выше абзац (и тот факт, что ничто не использует object_creator
) требует только создания экземпляра имени типа и имени объекта для получения эффекта, аналогичного описанному выше внешнему объявлению.
В результате GCC никогда не должен проверять, instance
действителен. Я бы сказал, что, учитывая вышеприведенный абзац, даже если у вас не было опечатки, вполне возможно, object_creator
не делает то, что вы думаете, что делает. Если ваш код работал, то только потому, что функция local static obj
была инициализирована при первом использовании (что делает ObjectCreator
избыточным).
Что касается того, почему добавление явного экземпляра (как @ P я предложил ) немедленно вызывает ошибку. Мы можем видеть здесь:
14.7.2 Явная реализация [temp.explicit]
7 Явная реализация шаблона класса
Специализация также явно создает экземпляр каждого из его членов (не
включая членов, унаследованных от базовых классов), чье определение
видимый в момент создания экземпляра и который ранее не был
явно специализируется на единице перевода, содержащей явное
конкретизации.
Когда мы делаем это, мы рекурсивно вынуждаем создавать все экземпляры и, в результате, проверять.
1 - это проект 2005 года. Очень близко к C ++ 03, и поэтому я считаю целесообразным, учитывая ваше использование GCC 4.4.7.