В 14.8.2.4p10 проекта C ++ 11 написано
Если для каждого рассматриваемого типа данный шаблон, по крайней мере, так же специализирован для всех типов и более специализирован для некоторого набора типов, а другой шаблон не более специализирован для каких-либо типов или, по крайней мере, не так специализирован для любых типов, то данный Шаблон более специализирован, чем другой шаблон.
Почему есть «или не так специализирован для каких-либо типов»? Насколько я вижу, если у нас есть список типов
T1, T2, T3
U1, U2, U3
И если все Ц хотя бы как специализированные, а некоторые более специализированные. И никто из Us не является более специализированным, тогда мне кажется, что из этого следует, что множество T в целом более специализировано, чем множество U, логически говоря. Почему тогда упоминается такой запасной вариант, когда никто из нас не настолько специализирован, как соответствующие Ц?
Обновление: это было добавлено как официальный выпуск C ++
Я наконец понял, как читать этот абзац. Ниже я маркировал это
Если для каждого рассматриваемого типа данный шаблон является как минимум специализированным для всех типов, и
- более специализированный для некоторого набора типов, а другой шаблон не более специализированный для каких-либо типов, или
- {другой шаблон} не менее специализирован для любых типов,
тогда данный шаблон более специализирован, чем другой шаблон.
Таким образом, следующий первый шаблон также более специализирован, чем второй шаблон
template<typename T> void f(T*);
template<typename T> void f(T);
Обратите внимание, что параметр первого шаблона, по крайней мере, столь же специализирован, как и второй шаблон, но не определен как «более специализированный» — этот термин применяется только в случае, когда оба параметра были ссылочными, и применяются определенные условия (см. Пункт 9 из 14.8. 2.4). Правила видимо не означало следовать любым формальным законам. Второй шаблон не настолько специализирован, как первый. Это означает, что применяется вторая пуля, а не первая.
Этот ответ основан на неправильном разборе абстрактного синтаксического дерева стандартного абзаца. Группировка условий, принятая в разделе «Назад к стандарту», оказалась не той, которая была запланирована. Предполагаемая группировка — та, которую Йоханнес Шауб показал в своем ответе.
Почему тогда упоминается такой запасной вариант, когда никто из нас не настолько специализирован, как соответствующие Ц?
Я согласен с вами, что вторая часть (фактически, все второе условие) является излишней.
Некоторая справочная лексика:
Давайте повеселимся с логикой и введем 3 фундаментальных отношения между двумя шаблонами для пары соответствующих параметров:
Ti
а также Ui
соответственно, один шаблон соответствует другому, но не наоборот. Я укажу это как Ti < Ui
;Ti
а также Ui
соответственно один шаблон соответствует другому а также наоборот. Я укажу это как Ti == Ui
;Ti
а также Ui
соответственно, никто шаблонов соответствует другому для конкретного параметра. Я укажу это как T1 ~ U1
,Например, во фрагменте кода ниже:
template<typename X> struct A { };
template<typename X> struct B { };
template<typename X> void foo(A<X>, X, A<X>) { } // 1
template<typename X> void foo(X, X, B<X>) { } // 2
Для первого параметра (1) более специализирован, чем (<
) (2); для второго параметра (1) в равной степени специализируется как (или «столь же специализированный как», ==
) (2); по третьему параметру (1) специализация несопоставима с (~
) (2).
И давайте теперь определим производное отношение:
Ti
а также Ui
когда (Ti < Ui)
или же (Ti == Ui)
то есть когда (1) более специализирован, чем (2), или (1) столь же специализирован, как (2). Следовательно, в приведенном выше примере T1 <= U1
, T2 <= U2
, а также U2 <= T2
,Вернуться к стандарту:
С помощью пары скобок приведенная выше цитата становится (A && (B1 || B2)):
[…] для каждого рассматриваемого типа:( данный шаблон как минимум специализирован для всех типов и
более специализированный для некоторого набора типов )AND
( другой шаблон не более специализирован для любых типов
OR
по крайней мере, не так специализирован для любых типов )
Даны два шаблона, которые нужно упорядочить относительно соответствующих последовательностей типов параметров T1, ..., Tn
а также U1, ..., Un
, условие (А):
[…] данный шаблон по крайней мере, как специализированный для всех типов и более специализированный для некоторого набора типов […]
Означает, что для каждого i = 1..n
, Ti <= Ui
и для некоторых j
в 1..n
, он применяет более строгое условие Tj < Uj
, Отбрасывание индекса i
это означает, что для каждого параметра:
(T < U) || (T == U) // (A)
Это условие помещается в логическое соединение («и») с другим условием (B), которое, в свою очередь, является логическим разделением («или») двух подусловий (B1) и (B2). Давайте начнем изучение подусловия (B1):
[…] другой шаблон не более специализирован для любых типов […]
Это означает, что для любого i
никогда не бывает Ui < Ti
, что означает, что либо:
Ti
более специализированный, чем Ui
(Ti < Ui
); или жеTi
а также Ui
одинаково специализированы (Ui == Ti
); или жеTi
а также Ui
несопоставимы по специализации (Ui ~ Ti
):Более формально:
!(U < T) <==> (T < U) || (T == U) || (T ~ U) // (B1)
Теперь давайте посмотрим на второе подусловие (B2), которое находится в логической дизъюнкции с (B1):
[…] по крайней мере не столь специализирован для любых типов […]
Это отрицание U <= T
, что значит:
!(U <= T) <==> !((U == T) || (U < T)) ==> !(U == T) && !(U < T)
Другими словами, T
а также U
не одинаково специализированы, ни U
более специализированный, чем T
, Следовательно, остаются только следующие возможности:
(T < U) || (T ~ U) // (B2)
Теперь очевидно, что (B2) влечет (B1), потому что (B2) является более ограничительным. Следовательно, их дизъюнкт (B) будет совпадать с (B1), а (B2) избыточен:
(T < U) || (T ~ U) || (T == U) // (B)
Но здесь также очевидно, что (A) является более строгим, чем (B), поэтому соединение (A) и (B) эквивалентно (A).
Заключение:
Все условие (B) является избыточным.