The compiler will always looks for the match that is most specialized (and will fail if there's ambiguity).
Since char** matches both patterns:
char** = T* (with T = char*)
char** = T (with T = char**)
and the former is more specialized, that will be chosen. (And since char** is really a pointer to something, I think "we are not achieving the functionality that we want" is false.)
Edit.
Once the specialization is chosen, all other candidates will be thrown out (recursive substitution will not happen in the matching phase). For instance,
template<class T> struct A {
typedef T type;
static const int value = 0;
};
template<class T> struct A<T*> {
typedef T type;
static const int value = 12;
};
template<class T> struct A<T********> {
typedef T type;
static const int value = 1024;
};
...
A<char**>::type x; // <-- Line X
std::cout << A<char**>::value << std::endl; // <-- Line Y
At Line X and Y, the template A is to be instantiated. You give the first template parameter as char**. A expects either a pattern of T******** or T* or T. The 2nd one is the best match, so template<class T> struct A<T*> will be chosen. The other two will be stroke out.
# FAIL. Not specialized enough. Remove this from consideration.
// template<class T> struct A {
// typedef T type;
// static const int value = 0;
// };
# WIN. Use with T = char*.
template<class T> struct A<T*> {
typedef T type;
static const int value = 12;
};
# FAIL. Does not match char**.
// template<class T> struct A<T********> {
// typedef T type;
// static const int value = 1024;
// };
After performing substitution it becomes
struct A<char**> {
typedef char* type;
static const int value = 12;
};
and Line X and Y shall become
/*A<char**>::type*/ char* x; // <-- Line X
std::cout << /*A<char**>::value*/ 12 << std::endl; // <-- Line Y
(Note:
template<class T> class Vector
is not a partial specialization,
template<class T> class Vector<T*>
this one is.)