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

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

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

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;

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

В этот момент

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

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

В этом примере создается

A<25> a;

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

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

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