Возможно, ваша путаница проистекает из того, как работает отношение "более специализировано, чем".Это частичный порядок , а не общий порядок - это означает, что с учетом двух специализаций шаблонов не всегда бывает так, что один является более специализированным, чем другой.
Комментарий Анона прав:Предположим, что третьей специализации не существует, и позже в вашем коде у вас было:
Promotion<Array<double>, Array<double> > foo;
(Конечно, вы, вероятно, не создадите переменную этого пустого типа структуры, но это просто самое простоеспособ форсировать его создание.)
Учитывая это объявление foo
, какая из 1-ых 2 специализаций будет выбрана?
- Применяется ли специализация 1 с
T = Array<double>
. - Применяется специализация 2 с
T1 = double
, T2 = double
.
Обе специализации применимы, поэтому нам нужно определить, какая из них "более специализированная", чем другая, и выбрать этуодин.Как?Мы скажем, что X
более специализирован, чем Y
, если он , по крайней мере, столь же специализирован , как Y
, но Y
не настолько специализирован, как X
.Хотя кажется, что это просто танцует вокруг проблемы, есть умное правило, которое мы можем использовать, чтобы ответить на этот новый вопрос:
X
по крайней мере так же специализирован, как Y
, если,независимо от того, какие типы мы присваиваем параметрам шаблона X
, результирующий тип всегда может соответствовать Y
.
Обратите внимание, что мы забываем о конкретных типах, задействованных в текущей реализации (в этом случае double
) - отношение "по крайней мере столь же специализировано, как" является свойством самих частичных специализаций и не зависит от конкретных реализаций.
Может ли специализация 1 всегда совпадатьпо специализации 2?Процесс немного похож на алгебру.Мы требуем, чтобы для любого типа T
мы могли найти типы T1
и T2
такие, что:
Promotion<Array<T1>, Array<T2> > = Promotion<T, T>
Это означает:
Array<T1> = T
Array<T2> = T
Так что ответ - нет.Если посмотреть только на первый подразумеваемый результат, заданный для любого типа T
, в общем случае невозможно найти тип T1
такой, что Array<T1>
такого же типа, как T
.(Это будет работать, если T
окажется Array<long>
, но не будет, если T
будет int
или char*
или большинством других типов.)
А как насчет обратного?Может ли специализация 2 всегда соответствовать специализации 1?Мы требуем, чтобы для любых типов T1
и T2
мы могли найти тип T
такой, что:
Promotion<T, T> = Promotion<Array<T1>, Array<T2> >
Подразумевается:
T = Array<T1>
T = Array<T2>
Таким образом, ответ снова нет.Для любого типа T1
всегда можно найти тип T
такой, что T
того же типа, что и Array<T1>
- просто буквально установить T = Array<T1>
.Но в целом другой тип T2
не обязательно должен совпадать с T1
, и если это не так (например, если T1 = bool
, но T2 = float
), то будет невозможно найти тип T
, которыйсовпадает с Array<T1>
и Array<T2>
.Таким образом, в общем случае невозможно найти такой тип T
.
. В этом случае не только ни одна специализация не является более специализированной, чем другая, ни даже не столь специализирована, как Другой.В результате, если возникает необходимость в создании экземпляра этого шаблонного класса, и обе специализации совпадают - как это происходит в примере, приведенном Аноном, - невозможно выбрать «лучший».