Подтвердить что ты не робот

Как использовать шаблон extern

Я просматривал рабочий проект N3291 С++ 0x. И мне было интересно узнать о шаблоне extern. Раздел 14.7.3 гласит:

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

FYI: термин "декларация с явным выражением" является стандартным для extern template. Это было определено в разделе 14.7.2.

Это звучит так, будто он говорит, что если вы используете extern template std::vector<int>, то делать любую из вещей, которые обычно неявно создают экземпляр std::vector<int>, не будут делать этого.

Следующий абзац более интересен:

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

FYI: термин "определение явного инстанцирования" является стандартным для этих вещей: template std::vector<int>. То есть без extern.

Для меня эти две вещи говорят, что extern template предотвращает неявное создание экземпляра, но это не предотвращает явное создание экземпляра. Поэтому, если вы это сделаете:

extern template std::vector<int>;
template std::vector<int>;

Вторая строка эффективно отрицает первое, явно делая то, что первая строка предотвращала неявно.

Проблема заключается в следующем: Visual Studio 2008, похоже, не согласна. Способ, которым я хочу использовать extern template, - это запретить пользователям неявно создавать некоторые часто используемые шаблоны, чтобы я мог явно создать их в файлах .cpp, чтобы сократить время компиляции. Шаблоны будут создаваться только один раз.

Проблема в том, что я должен в основном #ifdef вокруг них в VS2008. Потому что, если одна единица перевода увидит версию extern и не extern, она сделает победу версии extern, и никто никогда ее не выполнит. И затем приходят ошибки компоновщика.

Итак, мои вопросы:

  • Какое правильное поведение соответствует С++ 0x? Должно ли extern template предотвратить явное создание экземпляра или нет?
  • Если ответ на предыдущий вопрос заключается в том, что он не должен, то VS2008 ошибочен (предоставлен, он был написан задолго до спецификации, поэтому ему не нравится его ошибка). Как VS2010 справляется с этим? Выполняет ли оно правильное поведение extern template?
4b9b3361

Ответ 1

В нем говорится

За исключением... специализированных шаблонов шаблонов

Таким образом, это не относится к std::vector<int>, а к его членам (членам, которые не являются встроенными функциями-членами и, предположительно, не являются вложенными классами. К сожалению, нет ни одного термина, который ловит оба класса специализация шаблонов и специализации классов-членов шаблонов классов ". Таким образом, есть некоторые места, которые используют только первый, но означают также включение последнего). Итак, std::vector<int> и его вложенные классы (например, std::vector<int>::iterator, если он определен как вложенный класс) по-прежнему будут неявно создаваться при необходимости.