C ++: есть ли смысл использовать ключевое слово "extern" для шаблонов? - PullRequest
1 голос
/ 23 сентября 2019

Рассмотрим следующий пример:

fnc.h:

#include <iostream>

template <class T> //common template definition
void fnc()
{
    std::cout << "common";
}

fnc.cpp:

#include "fnc.h"

template<> //specialization for "int"
void fnc<int>()
{
    std::cout << "int";
}

main.cpp

#include "fnc.h"

extern template void fnc<int>(); // compiler will not generate fnc<int> and linker will be used to find "fnc<int>" in other object files

int main()
{
    fnc<double>(); //using instantiation from common template
    fnc<int>(); using specialization from "fnc.cpp"
}

Затем я заменяю extern template void fnc<int>(); на template<> void fnc<int>(); и предполагаю, что поведение будет таким же.Есть ли реальный смысл в использовании ключевого слова extern с шаблонами или оно было введено только для удобства чтения?

1 Ответ

3 голосов
/ 23 сентября 2019

Это не для специализаций.Технически то, что вы сделали, плохо сформировано, диагностика не требуется.У вас есть явное объявление объявление , но не соответствует определение .Явная специализация не учитывается при сопоставлении с предоставленной вами декларацией (хотя некоторые компиляторы реализуют ее так, чтобы скрыть факт).

Эта конструкция предназначена для отсрочки создания экземпляра, чтобы компилятор не пытался создать экземпляр шаблона в текущем модуле перевода.Таким образом, вы можете использовать его для полного сокрытия шаблона и показа только для конечного набора типов:

Заголовок:

template <class T>
void fnc();

extern template void fnc<int>(); // The instantiation is elsewhere.

Источник:

template <class T> //common template definition
void fnc()
{
    std::cout << "common";
}

template void fnc<int>(); // explicit instantiation

Илизапретить создание часто используемой специализации в каждом TU:

Общий заголовок:

#include <vector>
extern template std::vector<unsigned char>; // look for member definitions elsewhere.

Один исходный файл:

template std::vector<unsigned char>; // The member functions are defined in this TU

В последующем сценарии использования можно сохранитьво время компиляции.

...