Я просматривал рабочий проект 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
?