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

Почему инициализация константного зависимого типа в списке параметров шаблона запрещена стандартом?

В ответе на этот пост (частично), специализирующийся на параметре нестандартного шаблона зависимого типа", он сообщает:

Тип параметра шаблона, соответствующего специализированному аргумент non-type не должен зависеть от параметра специализация. [Пример:

template <class T, T t> struct C {};
template <class T> struct C<T, 1>; // error

template< int X, int (*array_ptr)[X] > class A {};
int array[5];
template< int X > class A<X,&array> { }; // error

-end пример]

Мой вопрос: почему это ограничение здесь? Существует, по крайней мере, один случай, когда я нахожу, что это ограничение мешает писать чистый код. Например.

template <typename T, T*>
struct test;

template <typename T>
struct test<T, nullptr> // or struct test<T, (T*)nullptr>
{
};

template <typename R, typename...ARGs, R(*fn)(ARGs...)>
struct test<R(ARGs...), fn>
{
};

Хотя я не уверен, что есть другие случаи, когда утверждение константы, основанной на типе, является проблемой, не имеющей никакого смысла.

У кого-нибудь есть причина, почему это так?

4b9b3361

Ответ 1

(IMHO) Наиболее распространенные причины, по которым стандарт запрещает определенную функцию:

  • Функция покрывается другим механизмом на языке, что делает его излишним.
  • Это противоречит существующей языковой логике и реализации, что делает ее реализацию потенциально нарушением кода.
  • Наследие: функция была в первую очередь упущена, и теперь мы создали много без нее, что она почти забыта (см. специализацию по частным функциям).

Сложность реализации редко бывает фактором, хотя для реализации компилятора может потребоваться некоторое время, чтобы догнать эволюцию на "жестком" материале.

Вы всегда можете обернуть свой шаблонный шаблонный параметр другим типом:

template < typename T1, typename T2 > 
struct Demo {}; // primary template

template < typename T > 
struct Demo<T, integral_constant<T, 0>> {}; // specialization

Я сомневаюсь, что этот хак относится к делу 1. Случай 3 всегда возможен, поэтому рассмотрим случай 2. Для этого нам нужно знать, какие соответствующие правила стандарт накладывает на классы шаблонов частичные специализации.

14.5.5 Частичные специализации шаблона шаблона

  1. Аргумент non-type неспециализирован, если он является именем непигового параметра. Все другие аргументы, отличные от типа, являются специализированными. (С1)

  2. В списке аргументов частичной специализации шаблона шаблона применяются следующие ограничения:

    • Частично специализированное выражение нетерабельного аргумента не должно включать параметр шаблона частичной специализации, за исключением случаев, когда выражение аргумента является простым идентификатором. (С2)
    • Тип параметра шаблона, соответствующего специализированному аргументу не-типа, не зависит от параметра специализации. (С3)

Я обозначил первые три C lauses, которые я нашел релевантными (третий - тот, о котором идет речь). Согласно C1 в нашем случае , у нас есть специализированный аргумент non-type, поэтому C2 должен стоять, но этот

template <class T, T t> struct C {};
template <class T> struct C<T, 1>;

на самом деле

template <class T, T t> struct C {};
template <class T> struct C<T, T(1)>; // notice the value initialization

поэтому частично специализированный аргумент non type T t включает параметр шаблона частичной специализации class T в выражении, отличном от идентификатора; кроме того, такие специализации связаны с class T в инициализации значений, которая всегда будет нарушением правил. Тогда C3 приходит и очищает это для нас, так что нам не придется делать этот вывод каждый раз.

До сих пор мы установили, что правила синхронизируются с самими собой, но это НЕ доказывает случай 2 (как только мы удаляем начальное ограничение, каждое другое связанное ограничение разваливается). Нам нужно было бы погрузиться в правила соответствия шаблонов шаблонов классов; частичное упорядочение считается вне сферы действия здесь, потому что, если мы сможем подготовить действительных кандидатов к программисту, чтобы собрать хорошо сформированную программу (т.е. не создавать неоднозначное использование шаблонов классов).

Раздел

Соответствие частичным специализациям шаблона шаблона [temp.class.spec.match]

описывает процесс "сопоставления шаблонов" (давайте или принимаем), связанные с специализацией шаблонов. Правило 1 - общий рабочий процесс процедуры, а последующие правила - это те, которые определяют правильность

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

  2. Аргумент шаблона, не относящийся к типу, также можно вывести из значения фактического аргумента шаблона параметра non-type первичного шаблона.

  3. В имени типа, которое относится к специализации шаблона класса (например, A), список аргументов должен соответствовать списку параметров шаблона основного шаблона. Шаблонные аргументы специализации выводятся из аргументов первичного шаблона.

Эти правила не нарушаются, разрешая, чтобы тип параметра шаблона, соответствующий специализированному аргументу не-типа, зависел от параметра специализации. Поэтому IMHO нет конкретной причины, почему мы не можем иметь эту функцию в будущих версиях языка: наследие виноват. К сожалению, мне не удалось найти какие-либо языковые предложения с инициативой представить эту функцию.