«Почему компилятор хочет, чтобы мы так специализировали структуру X» — это не то, о чем говорят сообщения об ошибках. Вам не нужно этого делать, и вам действительно не следует этого делать, если только вам не нужна частичная специализация и статический член, определенный только для этой частичной специализации.
Проблема в том, что template<typename T2, typename T = int> struct X
— это шаблон класса, который имеет два параметра шаблона. Тот факт, что второй имеет аргумент шаблона по умолчанию, не меняет того факта, что параметров по-прежнему два.
Итак, вам нужно определить член шаблона класса как принадлежащий шаблону класса с двумя параметрами, например:
template<typename T2, typename T>
double X<T2, T>::f = 14.0;
Соответствующие параграфы стандарта (N4527, действующий проект):
[14.5.1p3]
Когда функция-член, класс-член, перечисление членов, статический элемент-данные или шаблон-член шаблона класса определяются вне определения шаблона класса, определение члена определяется как определение шаблона, в котором шаблон -parameters — это параметры шаблона класса. Имена параметров шаблона, используемые в определении члена, могут отличаться от имен параметров шаблона, используемых в определении шаблона класса. Список аргументов шаблона, следующий за именем шаблона класса в определении члена, должен называть параметры в том же порядке, что и в списке параметров шаблона члена. Каждый пакет параметров шаблона должен быть дополнен многоточием в списке аргументов шаблона.
[14.1p9]
[...] аргумент-шаблона по умолчанию не должен указываться в списках-параметров-шаблонов определения члена шаблона класса, который появляется за пределами класс участника. [...]
Как указано в приведенной выше цитате, фактические имена параметров шаблона (T2
и T
) не имеют значения, они могут отличаться от имен в определении шаблона класса, но они должны соответствовать определению члена. То есть вы можете сделать это
template<typename T, typename U>
double X<T, U>::f = 14.0;
и он по-прежнему будет определять член правильного шаблона класса X
. Однако использование одних и тех же имен может облегчить понимание кода при чтении.
При определении частичной специализации перед определением f
в исходном примере template<typename T> double X<T>::f = 14.0;
становится допустимым определением члена f
частичной специализации template<typename T2> struct X<T2,int>
и только этого шаблона (частичные специализации сами по себе являются шаблонами). Элемент f
основного шаблона template<typename, typename> struct X
остается неопределенным.
Соответствующая формулировка содержится в [14.5.5.3p1]:
Список параметров шаблона члена частичной специализации шаблона класса должен соответствовать списку параметров шаблона частичной специализации шаблона класса. Список аргументов шаблона члена частичной специализации шаблона класса должен соответствовать списку аргументов шаблона частичной специализации шаблона класса. Специализация шаблона класса — это отдельный шаблон. Члены частичной специализации шаблона класса не связаны с членами основного шаблона. [...]
person
bogdan
schedule
25.07.2015