Не специализируйте шаблон, но перегрузите его. Компилятор выяснит, какой шаблон функции взять, упорядочив их в соответствии с их специализацией их типов параметров функции (это называется частичным упорядочением).
template<typename T1, typename T2>
inline string ToString(const std::pair<T1, T2>& x) {
std::ostringstream o;
if (!(o << "[" << x.first << "," << x.second << "]"))
throw BadConversion(string("ToString(pair<T1,T2>)"));
return o.str();
}
Как правило, частичное упорядочение приведет именно к тому, что вы ожидаете. Более подробно рассмотрим наличие этих двух функций
template<typename T> void f(T);
template<typename T, typename U> void f(pair<T, U>);
Теперь, чтобы увидеть, является ли один из них хотя бы столь же специализированным, как и другой, мы проверяем следующее для обоих шаблонов функций:
- выбрал какой-то уникальный тип для каждого параметра шаблона, подставив его в список параметров функции.
- Используя этот список параметров в качестве аргумента, сделайте вычет аргумента для другого шаблона (выполните виртуальный вызов с этими аргументами для этого другого шаблона). Если вычет успешен и преобразование не требуется (добавление const является таким).
Пример для вышесказанного:
- замена некоторого типа
X1
на T
дает нам некоторый тип, назовите его X1
. вычет аргумента X1
против pair<T, U>
не сработает. Так что первый не настолько специализирован, как второй шаблон.
- подстановка типов
Y1
и Y2
в pair<T, U>
приводит к pair<Y1, Y2>
. Делание аргумента против T
первого шаблона работает: T
будет выведено как pair<Y1, Y2>
. Так что второе, по крайней мере, столь же специализированное, как и первое.
Правило состоит в том, что шаблон функции A является более специализированным, чем другие B, если A, по крайней мере, так же специализирован, как B, но B, по крайней мере, не так специализирован, как A. Итак, вторая победа в нашем примере: более специализированный, и он будет выбран, если мы сможем в принципе вызвать обе функции шаблона.
Боюсь, этот обзор спешил, я сделал это только для параметров типа и пропустил некоторые детали. Загляните в 14.5.5.2
в C ++ Standard Spec, чтобы увидеть кровавые подробности. г