Для специализаций статических элементов, если вы не инициализируете член, он воспринимается как декларация специализации, которая просто говорит: "О, не создавайте экземпляр члена из основного шаблона, потому что существует специализированное определение где-то еще». Стоит отметить, что определение должно появиться в .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;
В вашем случае у вас указаны все параметры, что делает его не охватываемым одним правилом определения для разрешения нескольких определений.
person
Johannes Schaub - litb
schedule
26.02.2010
typename A
делал что-либо там. - person Mike DeSimone   schedule 26.02.2010