Для статических специализаций элементов, если вы не инициализируете элемент, он принимается как специализация декларация , которая просто говорит: «О, не создавайте экземпляр элемента из основного шаблона, потому что это специализированное определение где-то еще ". Следует отметить, что определение должно появиться в файле .cpp (в противном случае вы получите обратное: несколько определений), и объявление без инициализатора все равно должно быть помещено в заголовочный файл.
Теперь правильный синтаксис действительно следующий, и он должен не появляться в заголовочном файле, а в .cpp
файле
template<> int B<A, 1>::a[1] = { };
В заголовочном файле все равно должно отображаться следующее:
template<> int B<A, 1>::a[1];
Это будет служить специализацией декларации .
Из этого следует, что вы не можете специализировать элемент, который имеет только конструктор по умолчанию и не подлежит копированию, потому что вам потребуется этот синтаксис:
// needs a copy constructor!
template<> Type Class<Arguments>::member = Type();
C ++ 0x исправляет это:
// doesn't anymore need a copy constructor
template<> Type Class<Arguments>::member{};
Для стандартных людей среди нас вот цитаты:
14.7.3/6
Если шаблон, шаблон элемента или член шаблона класса явно специализированы, то эта специализация должна быть объявлена до первого использования этой специализации, что приведет к неявной реализации в каждой единице перевода, в которой такие использование происходит; Диагностика не требуется.
14.7.3/15
Явная специализация статического члена данных шаблона - это определение, если объявление включает инициализатор; в противном случае это декларация. [Примечание: нет синтаксиса для определения статического члена данных шаблона, который требует инициализации по умолчанию.
template<> X Q<int>::x;
Это объявление независимо от того, может ли X быть инициализирован по умолчанию (8.5). ]
3.2/3
Каждая программа должна содержать ровно одно определение каждой не встроенной функции или объекта, которая используется в этой программе; Диагностика не требуется.
3.2/5
Может быть несколько определений типа класса (раздел 9), типа перечисления (7.2), встроенной функции с внешней связью (7.1.2), шаблона класса (раздел 14), шаблона нестатической функции (14.5). .5), статический член данных шаблона класса (14.5.1.3), функция-член шаблона класса (14.5.1.1) или специализация шаблона, для которого некоторые параметры шаблона не указаны (14.7, 14.5.4) в программе [...]
Ограничение этого «для которого не указаны некоторые параметры шаблона» означает, что нам разрешено делать следующее, помещая его в заголовок (таким образом, возможно, имея несколько определений этой специализации):
template<> template<typename T>
Type OuterClass<int>::InnerClass<T>::StaticMember = 0;
В вашем случае у вас есть все указанные параметры, поэтому на него не распространяется одно правило определения для разрешения нескольких определений.