Подтвердить что ты не робот

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

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

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

Почему существует "или не является, по крайней мере, специализированным для любых типов"? Насколько я вижу, если у нас есть список типов

T1, T2, T3
U1, U2, U3

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

4b9b3361

Ответ 1

Обновление: теперь это добавлено как официальная проблема С++


Я наконец понял, как читать данный параграф. Ниже я маркировал его

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

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

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

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

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

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

Ответ 2

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


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

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


Некоторые словарные ссылки:

Давайте немного повеселимся с логикой и введем 3 фундаментальных отношения между двумя шаблонами для пары соответствующих параметров:

  • Более специализированный, чем: для параметров Ti и Ui, соответственно, один шаблон соответствует другому, но не наоборот. Я укажу это как Ti < Ui;
  • В равной степени специализированный: для параметров Ti и Ui, соответственно, один шаблон соответствует другим и наоборот. Я укажу это как Ti == Ui;
  • Специализация - несравнимая: для параметров Ti и Ui соответственно none шаблонов соответствует другой для конкретного параметра. Я укажу это как 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, условие (A):

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

означает, что для каждого 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) является избыточным.