Вы нашли ошибку компилятора.Я воспроизвел это с g++ (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1
.Обходной путь - оставить деструктор неявным образом по умолчанию.Ошибка компоновщика возникает только тогда, когда деструктор явно помечает его как значение по умолчанию (= default
).
В любом случае деструктор никогда не создается с внешним шаблоном.Отмечая класс шаблона как внешний, компилятор отмечает, что любые необходимые символы являются внешними.За исключением деструктора, он все еще определен в файле.Похоже, что добавление = default
с шаблоном extern приводит к тому, что компилятор думает, что деструктор будет определен в другом месте.
Раздувание кода вызвано шаблоном extern.Компилятор только создает экземпляры методов класса шаблона, которые фактически используются.Это обычно намного меньше, чем число, которое определено.Когда вы используете принудительное создание экземпляра класса с extern template
, компилятор генерирует код для всех методов (кроме деструктора, как вы только что обнаружили).
g++ -c -std=c++0x main.cpp
g++ -c -std=c++0x extern.cpp
g++ main.o extern.o
header.hpp
#pragma once
#include <iostream>
#include <string>
#include <typeinfo>
template< typename T >
class Foo
{
public:
Foo( void ) :
m_name( typeid(T).name() ),
m_t( T() )
{ }
// add or remove this to cause the error
~Foo( void ) = default;
void printer( void )
{
std::cout << m_name << std::endl;
}
T returner( void )
{
return m_t;;
}
private:
std::string m_name;
T m_t;
};
extern template class Foo<int>;
extern.cpp
#include "header.hpp"
template class Foo<int>;
main.cpp
#include "header.hpp"
int main()
{
Foo<int> fi;
fi.printer();
Foo<float> ff;
ff.printer();
}