Почему для частичной специализации в нетиповом аргументе запрещено использовать параметры вложенного шаблона
У меня есть этот код
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 в этом сценарии? Он не может и поэтому должен запретить код.