Как использовать шаблон extern - PullRequest
24 голосов
/ 29 июля 2011

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

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

К вашему сведению: термин "явное объявление экземпляра" является стандартным для extern template.Это было определено в разделе 14.7.2.

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

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

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

К вашему сведению: термин «явное определение экземпляра» является стандартным для следующих вещей: 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, и никто не сможет ее реализовать.А потом приходят ошибки компоновщика.

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

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

1 Ответ

7 голосов
/ 29 июля 2011

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

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

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

...