Использование `extern template` для предотвращения неявного создания экземпляра класса шаблона - PullRequest
6 голосов
/ 04 июня 2019

Рассмотрим следующий фрагмент кода:

template <typename>
struct X { };

extern template struct X<int>;

int main()
{
    X<int>{};
}

Он компилирует и связывает: живой пример на godbolt.org . Я ожидаю, что он не будет связываться из-за объявления extern template.

Насколько я понимаю, extern template означает: "пожалуйста, не создавайте экземпляр этой конкретной специализации шаблона в этом TU, он будет предоставлен другим TU, и вы можете ссылаться на него" .

Примеры / описания. Я видел isocpp и cppreference , кажется, подтверждают мою ментальную модель. Э.Г.

С https://en.cppreference.com/w/cpp/language/class_template:

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

Почему мой фрагмент кода ссылается? Что на самом деле здесь происходит?


РЕДАКТИРОВАТЬ - нашел это в последней версии стандарта:

[temp.explicit]

Если объект является предметом как явного объявления экземпляра, так и явного определения экземпляра в одной и той же единице перевода, определение должно следовать за объявлением. Сущность, которая является предметом явного объявления экземпляра и которая также используется таким образом, чтобы в противном случае вызвать неявное создание экземпляра в модуле перевода, должна быть объектом явного определения экземпляра где-то в программе; в противном случае программа некорректна, диагностика не требуется.

Означает ли это, что отправленный мною фрагмент кода неправильно сформирован, NDR ?

Ответы [ 2 ]

4 голосов
/ 04 июня 2019

Означает ли это, что фрагмент кода, который я разместил, неверен, NDR?

Да, точным предложением из [temp.explicit] / 13, которое вы цитировали.«Сущность» означает только это.Не имеет значения, если явное объявление экземпляра в противном случае не имеет нормативного эффекта.

4 голосов
/ 04 июня 2019

Почему мой фрагмент кода ссылается? Что на самом деле здесь происходит?

Ну, нет ничего на ссылку. Для того, чтобы рассмотреть эффекты явной реализации. От n3337:

[temp.explicit] (выделено мной)

10 За исключением встроенных функций и шаблона класса специализации , явные объявления экземпляров имеют эффект подавления неявной реализации объекта, которому они см. [Примечание: цель состоит в том, чтобы встроенная функция, которая является предмет явного объявления экземпляра все еще будет неявно создается при использовании odr ([basic.def.odr]), так что тело может быть рассмотрено для встраивания, но это не вне строки встроенная функция будет сгенерирована в модуле перевода. - конец примечание]

Таким образом, неявная реализация специализации шаблона класса X<int> не подавляется. Это также агрегат, поэтому его инициализация происходит встроенным образом, и нам не с чем связываться. Однако, если бы у него были какие-либо члены, эти были бы исключены в соответствии с пунктом 8 :

Явный экземпляр, который называет специализацию шаблона класса также явный экземпляр того же вида (объявление или определение) каждого из его членов (не включая членов, унаследованных из базовых классов), который ранее не был в блоке перевода, содержащем явную реализацию, кроме как описано ниже.

Так что если у вас вместо совокупности было что-то похожее на это:

template <typename>
struct X {
    X();
};

template <typename T>
X<T>::X() {}     

extern template struct X<int>;

int main()
{
    X<int>{};
}

Это не сработает, как вы ожидаете, поскольку в ODR используется конструктор, определение которого никогда не создается. Объявление является созданным экземпляром, потому что конкретизированная специализация создается, как упомянуто выше. Но мы никогда не получим никакого определения под подавляющим эффектом явного объявления экземпляра.

...