Почему для частичной специализации в нетиповом аргументе запрещено использовать параметры вложенного шаблона

У меня есть этот код

template<int N, bool C = true>
struct A;

template<int N>
struct A<N, !(N % 5)> {
  /* ... */
};

// should work
A<25> a;

То есть для чисел N которые делятся на 5Компилятор должен использовать частичную специализацию. Но компилятор не примет эту частичную специализацию, потому что стандарт требует, чтобы он отклонял такой код, когда нетипичный аргумент частичной специализации ссылается на параметр, а не просто на параметр (например, A<N, N> будет действительным). Но в чем причина этого?

Обратите внимание, что я могу просто изменить свой код на более многословный пример, и он действителен

template<bool> struct wrap;
template<int N, typename = wrap<true> >
struct A;

template<int N>
struct A<N, wrap<!(N % 5)> > {
  /* ... */
};

// should work
A<25> a;

Это нормально, потому что это больше не параметр типа. Но по какой причине спецификация запрещает более прямую частичную специализацию?

2 ответа

Решение

Я думаю, что многое из этого является историческим. Нетипичные параметры шаблона изначально вообще не допускались. Когда они были добавлены, было много ограничений. Поскольку люди пробовали разные возможности и подтвердили, что они не вызывают проблем, некоторые ограничения были сняты.

Некоторые из этих первоначальных ограничений остаются без особой причины, за исключением того факта, что никто не потрудился изменить их. Как и там, многие из них можно обойти, поэтому удаление их, как правило, не вызовет особых затруднений. В основном это сводится к вопросу о том, достаточно ли заботился кто-либо об этом конкретном случае, чтобы написать статью о нем.

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

С этой точки зрения

template<int N>
struct A<N, !(N % 5)> {
  /* ... */
};

N переменная, которая может принимать более одного значения, и компилятор не может вычислить N % 5 с уверенностью.

Ваш пример создает экземпляр использования

A<25> a;

но вы могли бы также иметь

A<25> a1;
A<15> a2;

Как компилятор выбирает значение для N в этом сценарии? Он не может и поэтому должен запретить код.

Другие вопросы по тегам