There are different levels of template specialization:
1) Template declaration (no specialization)
template <class Key, class Value>
struct Foo {};
2) Partial specialization
template <class Key>
struct Foo<Key, int> {};
3) Full/explicit specialization
template <>
struct Foo<std::string, int> {};
Then, when instantiating the templates, the compiler will choose the most specialized definition available:
Foo<std::string, std::string> f1; // Should match #1
Foo<int, int> f2; // Should match #2
Foo<std::string, int> f3; // Should match #3
#1 and #3 work for template functions as well.