user3882729
user3882729

Reputation: 1534

How does partial specialization work for non type template parameters?

I would like to understand how the standard determines which partial specialization to pick below. For example, does it have anything to do with number of template parameters in the specialization? Otherwise, how does it determine the "best-fit" match?

#include <cstdint>

template <int ...I>
struct Vector;

template <typename T>
struct Transform;

template <int x, int ...I>
struct Transform<Vector<x,x,I...>> {
   using type = int;
};

template <int ...I>
struct Transform<Vector<I...>> {
   using type = char;
};

int main() {
    static_assert(sizeof(Transform<Vector<1,1,2>>::type) == 4);
}

Upvotes: 3

Views: 72

Answers (1)

ALX23z
ALX23z

Reputation: 4713

No, it works differently. It has some dominance functionality. If a specialization is clearly further specializes another then it is chosen but otherwise it is ambiguous. The method isn't too intelligent and is meant to deal with simple cases. In any complicated case you'd better make sure there is no ambiguity at all.

For instance, neither

template <int x, int y, int ...I>
struct Transform<Vector<x, y, y, y, I...>> {
     using type = short;
};

nor

template <int x, int y, int ...I>
struct Transform<Vector<x, y, y, x, I...>> {
     using type = short;
};

is a further specialization of the two x case

template <int x, int ...I>
struct Transform<Vector<x, x, I...>> {
   using type = int;
};

So if you were to declare either one then Transform<Vector<1,1,1,1>> would be ambiguous. To resolve it you'd have to define the specialization for Vector<x, x, x, x, I...> or restrict the previous ones.

However, if instead of the above you were to define

template <int x, int y, int ...I>
struct Transform<Vector<x, x, y, y, I...>> {
     using type = short;
};

Then it would be the chosen form for Transform<Vector<1,1,1,1>> - as this clearly further specializes the two x case.

Upvotes: 1

Related Questions