Ошибка неоднозначности вызова функции шаблона

Я не знаком с шаблонами. Я только начал изучать его. Почему я получаю ошибки в следующей программе?

#include <iostream>
#include <string>
using std::cout;
using std::string;
template<class C>
C min(C a,C b) {
    return a<b?a:b;
}
int main()
{
    string a="first string";
    string b="second string";
    cout<<"minimum string is: "<<min(a,b)<<'\n';
    int c=3,d=5;
    cout<<"minimum number is: "<<min(c,d)<<'\n';
    double e{3.3},f{6.6};
    cout<<"minimum number is: "<<min(e,f)<<'\n';
    char g{'a'},h{'b'};
    cout<<"minimum number is: "<<min(g,h)<<'\n';
    return 0;
}

Ошибки:

13  [Error] call of overloaded 'min(std::string&, std::string&)' is ambiguous

6   [Note] C min(C, C) [with C = std::basic_string<char>]

Пожалуйста, помогите мне.

Ответ 1

Здесь есть две вещи.

Ваша первая проблема заключается в том, что вы включили только часть сообщения об ошибке. Вот ссылка на код, выполняемый в gcc и clang, и одно из полученных сообщений об ошибках (в полном объеме):

main.cpp:13:34: error: call to 'min' is ambiguous
    cout<<"minimum string is: "<<min(a,b)<<'\n';
                                 ^~~
/usr/include/c++/v1/algorithm:2579:1: note: candidate function [with _Tp = std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >]
min(const _Tp& __a, const _Tp& __b)
^
main.cpp:6:3: note: candidate function [with C = std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >]
C min(C a,C b) {
  ^

есть два кандидата. Один в main.cpp:6:3 (строка 6, символ 3) и один в algorithm:2579:1 (строка 2579, символ 1).

Один из них вы написали, а один из них - в #include <algorithm>.

Один из ваших файлов заголовков включил <algorithm> без вашего запроса. Стандартным заголовкам разрешено делать это так же раздражающе, как иногда бывает.

В <algorithm> есть шаблон функции std::min. Поскольку std::string является экземпляром класса шаблона в namespace std, шаблон функции std::min находится через процесс, называемый "зависимым от аргумента поиска" или "поиском Koenig". (кандидаты на перегрузку функции ищутся локально, а также в пространствах имен аргументов функции, а также в пространствах имен аргументов шаблона аргументам функции и в пространствах имен вещей, на которые указывают аргументы функция и т.д.)

Также найдена ваша локальная функция min, так как она находится в том же пространстве имен, что и тело main.

Оба одинаково хороши, и компилятор не может решить, какой из них вы хотите вызвать. Поэтому он генерирует сообщение об ошибке.

Оба gcc и clang do error:, затем последовательность note: s. Обычно все note: после ошибки важны для понимания ошибки.

Чтобы исправить это, попробуйте позвонить ::min (полностью откликнуться на вызов) или переименовать функцию на что-то другое или сделать вашу версию более подходящей, чем std::min (сложная, но выполнимая в некоторых случаях), или вызов (min)(a,b). Последние блоки ADL/Koenig lookup, а также блокирует расширение макросов (например, если какая-то ОС ввела макрокоманды #define min в свои системные заголовки) (через @0x499602D2).

Ответ 2

Вы столкнулись с столкновением имен с std::min. Вероятно, он включен в один из других стандартных заголовков библиотек, которые вы включили, либо <iostream>, либо <string>, моя догадка, вероятно, последняя. Быстрое исправление заключается в переименовании вашей функции. Например, переименование его на mymin отлично работает. Демо