Ответ 1
Для статических членских специализаций, если вы не инициализируете член, это берется как объявление специализации, которое просто говорит: "О, не создавайте экземпляр элемента из основного шаблона, потому что есть специализированное определение где-то в другом месте". Следует отметить, что определение должно появиться в файле .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();
С++ 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;
В вашем случае у вас есть все указанные параметры, что делает его не охватываемым одним правилом определения для разрешения нескольких определений.