c++partial-specialization

Why is it disallowed for partial specialization in a non-type argument to use nested template parameters


I have this code

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

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

// should work
A<25> a;

That is, for numbers N that are divisible by 5, the compiler should use the partial specialization. But the compiler won't accept that partial specialization, because the Standard requires it to reject such code where a non-type argument of a partial specialization references a parameter and is not simply a parameter (like, A<N, N> would be valid). But what is the reason of doing so?

Note that I can simply change my code to a more wordy example and it is valid

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;

This is fine because it's not a non-type parameter anymore. But what is the reason the spec forbids the more straightforward partial specialization?


Solution

  • I think a lot of it is historical. Non-type template parameters weren't originally allowed at all. When they were added, there were lots of limitations. As people tried different possibilities, and confirmed that they didn't cause problems, some of the limitations were removed.

    Some of those original limitations remain for no particular reason beyond the fact that nobody bothered to work at changing them. Much like there, many of them can be worked around so removing them generally often wouldn't cause any particular difficulty. Mostly it comes down to a question of whether anybody cared enough about this particular case to write a paper about it.