В этом коде несколько ошибок. Сначала первоначальная идея не очень хорошая. У вас есть два глобальных статических объекта: a
и A::data
. Порядок, в котором они инициализируются, не определен. В зависимости от настроения вашего компилятора у вас есть 50% шанс, что конструктор a
будет вызван первым и попытается записать что-то в неинициализированный A::data
.
Это иногда называют статической проблемой порядка инициации фиаско . Предлагаемое решение - превратить такие объекты в локальные статические объекты, переместив их в функции:
#include <map>
#include <iostream>
template <typename T>
class A
{
std::map<int, int> &data()
{
static std::map<int, int> d;
return d;
}
public:
A()
{
std::cout << data().size() << std::endl;
data()[3] = 4;
}
};
int main()
{
A<char> a;
return 0;
}
Локальные статические объекты инициализируются при первом вызове функции.
О закомментированной "явной реализации", которую вы забыли template <>
.
Но после того, как вы добавите к этой строке префикс template <>
, это все равно будет не определение , а объявление . Он объявляет, что есть определение A :: data где-то еще . Чтобы действительно определить его, вам нужно инициализировать его чем-то, см., Например, ответ Джека Ллойда.