Ну, я думаю, я просто запутался в явной реализации шаблона ~> _<~
Также см. Следующий код:
#include <iostream>
#include <vector>
std::vector<int> a; // Implicit instantiation definition.
// Explicit instantiation declaration.
extern template class std::vector<int>;
int main() {
std::cout << std::vector<int>().size(); // So what?
}
Это вызывает ошибку ссылки
/tmp/ccQld7ol.o: In function `_GLOBAL__sub_I_a':
main.cpp:(.text.startup+0x6e): undefined reference to `std::vector<int, std::allocator<int> >::~vector()'
collect2: error: ld returned 1 exit status
с GCC 5.2, но хорошо работает с clang 3.6. Какой из них правильный в соответствии со стандартом?
Я надеюсь, что есть проницательный способ понять явную реализацию шаблона, чтобы можно было логически вывести и объяснить ответы на все вопросы выше.
Сущность, которая является предметом явного объявления экземпляра
и это также используется таким образом, что в противном случае вызвало бы неявное
создание экземпляра (14.7.1) в блоке перевода должно быть предметом
явное определение экземпляра где-то в программе;
в противном случае программа некорректна, диагностика не требуется.
Во-первых, кажется, что вы недооцениваете явное воплощение. В этом нет ничего особенного. Все, что он делает, это позволяет кому-то использовать шаблонную функцию или класс без видимого определения шаблона. Это достигается за счет создания экземпляра функции или класса с указанным шаблоном, чтобы он больше не был шаблоном, а фактически использовался. Его можно использовать, например, когда у вас есть класс шаблона, но вы хотите скрыть фактический код в файле .cpp, который вы никогда не предоставляете пользователям — вместо этого вы даете им скомпилированный файл .o. Чтобы заставить его работать, вы можете явно создать экземпляр шаблона с типами, которые, по вашему мнению, понадобятся пользователям для аргументов шаблона. (конечно, это редкий случай, когда набор типов известен как этот). В этом нет ничего более.
Неявные и явные экземпляры для одного и того же типа могут жить вместе. Неявная реализация создаст слабый символ, явная — «сильный» символ. Сильные символы переопределяют слабые символы, и нет нарушения ODR. Все будет хорошо.
Что касается вашей ошибки, вам нужно удалить extern из вашего явного экземпляра.