Не шаблон, который не требует преобразования, всегда лучше подходит.То есть, если бы это были единственные определения min()
, проблем не было бы (т. Е. Переименование функции min
во что-то еще устранило бы неоднозначность).Неоднозначность находится между template <typename T> T const& std::min(T const&, T const&)
и вашей шаблонной версией.Другое исправление заключается в удалении объявления using и явной квалификации имен из пространства имен std
, то есть следующий код компилируется нормально:
#include <iostream>
#include <string>
template <class T> T min(T a, T b) {
return a < b? a: b;
}
std::string min(std::string str1, std::string str2) {
return str1.length() < str2.length()? str1: str2;
}
int main()
{
int n=12, p=15;
std::string str1= "monsieur", str2= "bonjour" ;
std::cout << min(n,p) << "\n";
std::cout << min(str1, str2) << "\n";
}
Обратите внимание, что версия std::string
вашей min()
равна не специализация, а перегрузка!При вызове функции, как вы сделали, это не имеет значения, и она выберет версию, как и ожидалось.Однако при вызове функции при явном указании аргумента шаблона она не будет:
min(str1, str2); // calls string overload
min<std::string>(str1, str2); // calls the function template (*)
(*) На самом деле, min<std::string>(str1, str2)
, опять-таки, неоднозначна с версией из пространства имен std
из-за зависимости аргументауважать;если бы он был назван по-другому, он вызвал бы версию шаблона.
Если вы хотите действительно специализировать функцию, вы бы написали что-то вроде этого:
template <> std::string min<std::string>(std::string, std::string) { ... }
Тем не менее, здесь есть несколько случайныхпримечания к программе, не связанные с неоднозначностью и специализацией:
- В C ++
main()
всегда должно быть объявлено для возврата int
.В main()
разрешено пропускать оператор return, но некоторые компиляторы не получают этого права.Для переносимого кода лучше всего использовать возврат int
и просто возвращать 0
(или EXIT_SUCCESS<code> declared in <code><stdlib.h>
). - Вы почти наверняка захотите передать эти аргументы
const
ссылка: копированиеСтроки не такие дорогие, особенно для небольших std::string
с (поскольку современные реализации std::string
, похоже, используют оптимизацию небольших строк), но они также не бесплатны.Если объекты достаточно большие, это может привести к проблемам с производительностью. - Я предполагаю, что это всего лишь тест на перегрузку / специализацию.В противном случае,
std::string
версия min()
не рекомендуется, поскольку она ведет себя непредвиденным образом. - ваши тестовые строки выбраны неправильно, поскольку они не показывают, что перегрузка / специализация действительно используется.
std::endl
чрезмерно используется и делает что-то не так, как думает большинство людей: помимо вставки символа новой строки ('\ n'), он также сбрасывает std :: ostream .Это последняя часть, которая становится неожиданностью, и я обнаружил, что она создает серьезные проблемы с производительностью довольно часто.Если вы действительно не собираетесь очищать поток, просто напишите \ n .