Как C ++ связывает экземпляры шаблона - PullRequest
12 голосов
/ 23 февраля 2011

Если я определяю функцию (может быть, функцию-член класса, но не встроенную) в заголовочном файле, который включается двумя различными единицами перевода, я получаю ошибку ссылки, так как эта функция многократно определена.С шаблонами это не так, поскольку они не являются компилируемыми типами, пока компилятор не разрешит объявление объекта шаблонизированного типа.Это заставило меня понять, что я не знаю, где находится код скомпилированного шаблона и как он связан, поскольку C ++ не просто создает несколько копий кода для определения SomeTemplateClass.Любая информация приветствуется.Спасибо!

Ответы [ 4 ]

26 голосов
/ 23 февраля 2011

Существует 3 схемы реализации, используемые компиляторами C ++:

  • жадные экземпляры, где компилятор создает экземпляры в каждом модуле компиляции, который его использует, затем компоновщик отбрасывает все, кроме одногоиз них (это не просто оптимизация по размеру кода, это требуется для того, чтобы адреса функций, static переменных и тому подобное были уникальными).Это наиболее распространенная модель.

  • запрашиваемая реализация, где у компилятора есть база данных уже выполненных реализаций.Когда требуется создание экземпляра, БД проверяется и обновляется.Единственный известный мне компилятор, который использует его, это Sun, и он больше не используется по умолчанию.

  • повторное создание экземпляров, где создания выполняются компоновщиком (либо напрямую, либо путем назначения)их в блок компиляции, который затем будет перекомпилирован).Это модель, используемая CFront, то есть исторически она была первой, а также компиляторами, использующими интерфейс EDG (с некоторыми оптимизациями по сравнению с CFront).

(См. Шаблоны C ++, Полное руководство Дэвида Вандевурда и Николая Йосуттиса. Другая онлайн-ссылка - http://www.bourguet.org/v2/cpplang/export.pdf,, которая больше касается модели компиляции, но все еще содержит описания механизмов реализации).

2 голосов
/ 23 февраля 2011

Все функции шаблона неявно встроены. Так же, как методы, определенные в объявлении класса, неявно встроены.

Когда я говорю неявно inline, я имею в виду более современное использование этого слова. Смотрите мое длинное описание здесь .

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

Где хранятся экземпляры шаблонов?
Они хранятся так же, как и встроенные функции. Подробности этого зависят от компилятора.

2 голосов
/ 23 февраля 2011

Это зависит от реализации.

Некоторые компиляторы будут генерировать одни и те же экземпляры шаблона снова и снова для каждой единицы перевода, в которой они созданы, и позволить компоновщику сворачивать дубликаты.
Шаблоны получили плохую репутацию «раздувания кода», когда компоновщики еще не выполнили эту задачу. В настоящее время это, вероятно, незаслуженно. Некоторые реализации даже сворачивают разные экземпляры, когда они компилируются в один и тот же целевой машинный код. (Подобно f<A*>() и f<B*>(), поскольку типы указателей - это просто адреса в сгенерированном машинном коде.)

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

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

С export требовалось, чтобы компиляторы предварительно компилировали код шаблона и создавали его по запросу. Однако, за исключением одного поставщика, никто не реализовал export для своего компилятора, и теперь он удален.

0 голосов
/ 23 февраля 2011

Это на самом деле создает несколько копий.Эти копии являются специальными и не нарушают правило одного определения.Придут некоторые компоновщики, удалят копии и перекомпонируют функции, используя их;не все делают.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...