Компилятор будет генерировать код для каждого экземпляра шаблона при использовании шаблона на этапе компиляции. В процессе компиляции и компоновки файлы .cpp преобразуются в чистый объектный или машинный код, который содержит ссылки или неопределенные символы, поскольку файлы .h, включенные в ваш main.cpp, не имеют реализации YET. Они готовы к связыванию с другим объектным файлом, который определяет реализацию для вашего шаблона, и, таким образом, у вас есть полный исполняемый файл a.out.
Однако, поскольку шаблоны необходимо обрабатывать на этапе компиляции, чтобы генерировать код для каждого экземпляра шаблона, который вы определяете, поэтому простая компиляция шаблона отдельно от его заголовочного файла не будет работать, потому что они всегда идут рука об руку по самой причине что каждый экземпляр шаблона является совершенно новым классом буквально. В обычном классе вы можете разделить .h и .cpp, потому что .h является планом этого класса, а .cpp - это необработанная реализация, поэтому любые файлы реализации можно регулярно компилировать и связывать, однако использование шаблонов .h - это план того, как класс должен выглядеть не так, как должен выглядеть объект, а это означает, что файл .cpp шаблона не является обычной обычной реализацией класса, это просто план для класса, поэтому любая реализация файла шаблона .h может
Поэтому шаблоны никогда не компилируются отдельно и компилируются только там, где у вас есть конкретный экземпляр в каком-либо другом исходном файле. Тем не менее, конкретный экземпляр должен знать реализацию файла шаблона, потому что просто изменивtypename T
использование конкретного типа в файле .h не поможет, потому что там есть ссылки на .cpp, я не могу найти их позже, потому что помните, что шаблоны абстрактны и не могут быть скомпилированы, поэтому я вынужден дать реализацию прямо сейчас, чтобы я знал, что компилировать и связывать, и теперь, когда у меня есть реализация, она связывается с прилагаемым исходным файлом. По сути, в тот момент, когда я создаю экземпляр шаблона, мне нужно создать целый новый класс, и я не могу этого сделать, если не знаю, как должен выглядеть этот класс при использовании предоставляемого мной типа, если я не сделаю уведомления компилятору реализация шаблона, так что теперь компилятор может заменить T
мой тип и создать конкретный класс, который готов к компиляции и компоновке.
Подводя итог, шаблоны - это чертежи того, как должны выглядеть классы, а классы - это чертежи того, как должен выглядеть объект. Я не могу скомпилировать шаблоны отдельно от их конкретной реализации, потому что компилятор компилирует только конкретные типы, иными словами, шаблоны, по крайней мере, в C ++, являются чистой языковой абстракцией. Мы должны де-абстрагировать шаблоны, так сказать, и делаем это, давая им конкретный тип для работы, чтобы наша абстракция шаблона могла трансформироваться в обычный файл класса и, в свою очередь, может быть скомпилирована нормально. Разделение файла шаблона .h и файла шаблона .cpp не имеет смысла. Это бессмысленно, потому что разделение .cpp и .h происходит только тогда, когда .cpp можно скомпилировать по отдельности и связать индивидуально, с помощью шаблонов, поскольку мы не можем скомпилировать их отдельно, потому что шаблоны являются абстракцией,
Это означает, что typename T
get заменяется на этапе компиляции, а не на этапе компоновки, поэтому, если я попытаюсь скомпилировать шаблон без T
замены в качестве конкретного типа значения, который абсолютно бессмыслен для компилятора, и, как результат, код объекта не может быть создан, потому что он не создает знать что T
есть.
Технически возможно создать какую-то функциональность, которая сохранит файл template.cpp и переключит типы, когда он найдет их в других источниках. Я думаю, что в стандарте есть ключевое слово export
, которое позволит вам размещать шаблоны в отдельном файле. Cpp файл, но не так много компиляторов фактически реализуют это.
Просто примечание: при создании специализаций для шаблонного класса вы можете отделить заголовок от реализации, потому что специализация по определению означает, что я специализируюсь на конкретном типе, который можно скомпилировать и связать по отдельности.