Функция шаблона в не шаблонном классе - Разделение между файлами H и CPP - PullRequest
5 голосов
/ 25 января 2012

У меня было (и у меня долгое время) впечатление, что вам нужно было полностью определить все функции шаблона в ваших файлах .h, чтобы избежать множества ошибок определения, возникающих из-за процесса компиляции шаблона (не на C ++ 11). ).

Я читал код сотрудника, и у него был не шаблонный класс, в котором была объявлена ​​функция шаблона, и он отделил объявление функции от определения функции (объявленной в H, определенной в CPP). К моему удивлению, он компилируется и работает нормально.

Есть ли разница между тем, как компилируется функция шаблона в не шаблонном классе, и как компилируется функция в классе шаблона? Может кто-нибудь объяснить, в чем эта разница или где я могу быть смущен?

Ответы [ 2 ]

5 голосов
/ 25 января 2012

Интересным моментом является то, как и когда создается экземпляр шаблона.Если экземпляры могут быть найдены во время ссылки, шаблон definition не должен быть видимым в заголовочном файле.

Иногда явные экземпляры могут быть вызваны так:

  • header:

    struct X { 
        // function template _declaration_
        template <typename T> void test(const T&);
    };
    
  • cpp:

    #include "X.h"
    
    // function template _definition_:
    template <typename T> 
        void X::test(const T&)
    {
    }
    
    // explicit function template _instantiation(s)_:
    template X::test<int>(const int&);    
    template X::test<std::string>(const std::string&);
    

При использовании этого примера соединение будет успешным, если толькоНеопределенные определения шаблона используются в других единицах перевода

3 голосов
/ 25 января 2012

Нет разницы между шаблонами функций, определенными в пространстве имен или в области видимости класса.Также не имеет значения, находится ли внутри шаблон класса или нет.Важно то, что в какой-то момент в проекте создается экземпляр любого используемого шаблона функции (независимо от того, является ли он членом или не членом).Давайте рассмотрим различные ситуации:

  1. Неиспользуемые шаблоны функций не нужно создавать, поэтому их реализация не должна быть видна компилятору в любой момент времени.Это звучит скучно, но важно, например, при использовании подходов SFINAE, где шаблоны классов или функций объявлены, но не определены.
  2. Любой шаблон функции, который определен там, где он используется, будет создан экземпляром компилятором в форме, которая позволяет несколькоопределения в разных единицах перевода: сохраняется только один экземпляр.Важно, чтобы все различные определения были объединены, потому что вы можете обнаружить различия, если вы взяли адрес шаблона функции или использовали переменную состояния внутри шаблона функции: для каждого экземпляра должно быть только одно из них.
  3. Наиболее интересная настройка - это когда шаблон функции определяется как , а не при использовании шаблона функции: в этом случае компилятор не может его создать.Когда компилятор видит определение шаблона функции в другом модуле перевода, он не знает, какие аргументы шаблона нужно создать!A Улов 22 * ​​1011 *?Ну, вы всегда можете явно создать экземпляр шаблона один раз.Наличие нескольких явных экземпляров создаст несколько определенных символов.

Это примерно важные параметры.Часто есть веские причины, по которым вы не хотите иметь определение шаблона функции в заголовке.Например, вы не обязательно хотите перетаскивать зависимости, которых у вас не было бы иначе.Поместить определение шаблона функции в другое место и явно создать его экземпляр - это хорошо.Кроме того, вы можете захотеть сократить время компиляции, например, избегая по существу создания экземпляров всего потока ввода-вывода и библиотеки локали в каждой единице перевода, использующей поток.В C ++ 2011 были введены внешние шаблоны , которые позволяют объявлять, что определенный шаблон (шаблон функции или класс) определяется один раз для всей программы, и нет необходимости создавать его в каждом заголовке с помощьюособенно распространенные аргументы шаблона.

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

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