Extern template



Дисклеймер: здесь и далее в этой серии статей я буду называть "специализацией" шаблона его инстанциацию с конкретным шаблонным параметром.



Помните, как мы явно инстанцировали шаблон в файле реализации? Раз мы может сказать компилятору, чтобы он инстанцировал нужную специализацию в нужном нам файле, то очень удобно потом обращаться за кодом этой специализации конкретно в эту единицу трансляции. Потому что, как мы уже знаем, код одной и той же специализации может генерироваться во всех единицах трансляции, не вызывая при этом конфликтов и нарушения ODR(вектор интов инстанцируется много где, но никогда эти специализации не конфликтуют при линковке). Тут аналогия с inline сущностями.



В общем, хочется иметь один образцово-показательный код в одной TU и обращаться за нужными символами туда.



И такой инструмент есть!



Называется extern template declaration. Этот пост, а также несколько предыдущих и следующих, посвящается нашему олду @PyXiion и его просьбе разобрать этот вопрос.



Идея очень похожа на extern объявления других сущностей. С его помощью обеспечивается внешнее связывание и оно помогает компилятору понять, что такая сущность в программе есть, просто она описана в другой единице трансляции. Это значит, что на этапе линковки компилятор может посмотреть в эту самую другую TU и найти там все, что нужно для генерации полноценного кода.



Синтаксис следующий:



extern template class-key template-name <argument-list>;



Все то же самое, что и при явной инстанциации, только спереди добавляем extern. Фича из С++11 кстати и скорее всего средний разработчик даже не представляет о ее существовании.



Что происходит, когда мы добавляем эту строчку после определения шаблона? Неявная конкретизация этой специализации запрещается. То есть даже если компилятор видит полное определение шаблона и вы создаете объект конкретной специализации, то код для нее генерироваться не будет. Вместо этого компилятор будет ждать, что он найдет нужные символы и код для них в другой единице трансляции.



В основном, эта вещь решает проблему дублирования кода специализации во всех TU, где она используется. Очевидно, что если все TU будут обращаться к одной единственной за всем нужным, а не будут генерировать все сами, то будет всего один оригинал кода и соотвественно размер бинаря уменьшится. Как и время компиляции собственно.



Как это работает и какие еще проблемы решает эта фича, мы рассмотрим в следующих частях, все в один пост не влезет, много тонких моментов, требующих акцентов.



Learn new things. Stay cool.



#cppcore #cpp11 #template #compiler