Когда шаблон более специализирован, чем другой? «И» / «Или» путаница с логикой.

В 14.8.2.4p10 проекта C ++ 11 написано

Если для каждого рассматриваемого типа данный шаблон, по крайней мере, так же специализирован для всех типов и более специализирован для некоторого набора типов, а другой шаблон не более специализирован для каких-либо типов или, по крайней мере, не так специализирован для любых типов, то данный Шаблон более специализирован, чем другой шаблон.

Почему есть «или не так специализирован для каких-либо типов»? Насколько я вижу, если у нас есть список типов

T1, T2, T3
U1, U2, U3

И если все Ц хотя бы как специализированные, а некоторые более специализированные. И никто из Us не является более специализированным, тогда мне кажется, что из этого следует, что множество T в целом более специализировано, чем множество U, логически говоря. Почему тогда упоминается такой запасной вариант, когда никто из нас не настолько специализирован, как соответствующие Ц?

13

Решение

Обновление: это было добавлено как официальный выпуск C ++


Я наконец понял, как читать этот абзац. Ниже я маркировал это

Если для каждого рассматриваемого типа данный шаблон является как минимум специализированным для всех типов, и

  • более специализированный для некоторого набора типов, а другой шаблон не более специализированный для каких-либо типов, или
  • {другой шаблон} не менее специализирован для любых типов,

тогда данный шаблон более специализирован, чем другой шаблон.

Таким образом, следующий первый шаблон также более специализирован, чем второй шаблон

template<typename T> void f(T*);
template<typename T> void f(T);

Обратите внимание, что параметр первого шаблона, по крайней мере, столь же специализирован, как и второй шаблон, но не определен как «более специализированный» — этот термин применяется только в случае, когда оба параметра были ссылочными, и применяются определенные условия (см. Пункт 9 из 14.8. 2.4). Правила видимо не означало следовать любым формальным законам. Второй шаблон не настолько специализирован, как первый. Это означает, что применяется вторая пуля, а не первая.

7

Другие решения

Этот ответ основан на неправильном разборе абстрактного синтаксического дерева стандартного абзаца. Группировка условий, принятая в разделе «Назад к стандарту», ​​оказалась не той, которая была запланирована. Предполагаемая группировка — та, которую Йоханнес Шауб показал в своем ответе.


Почему тогда упоминается такой запасной вариант, когда никто из нас не настолько специализирован, как соответствующие Ц?

Я согласен с вами, что вторая часть (фактически, все второе условие) является излишней.


Некоторая справочная лексика:

Давайте повеселимся с логикой и введем 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).

И давайте теперь определим производное отношение:

  • Шаблон (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) является избыточным.

6

По вопросам рекламы [email protected]