2015-05-15 18 views
11

Nie znam szablonów. Właśnie zacząłem się uczyć. Dlaczego dostaję błędy w następującym programie?Błąd wywoływania funkcji niejednoznaczności szablonu

#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; 
} 

Błędy:

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

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

Proszę mi pomóc.

+1

Jakiego kompilatora używasz? Zrobiłoby to twoje '' ma zdefiniowaną w nim funkcję min. – NathanOliver

+0

Zmieniłem nazwę klasy i działa ona poprawnie (http://ideone.com/ygVUcr). Nie wiem, dlaczego 'min' koliduje z' std :: min'. – Mahesh

+0

@Mahesh: Czy odtworzyć problem bez zmiany jego nazwy? –

Odpowiedz

14

Tu dzieje się dwie rzeczy.

Twój pierwszy problem polega na tym, że zawierałeś tylko część komunikatu o błędzie. Here is a link to the code being complied in gcc and clang, a jeden z otrzymanych komunikatów o błędach (w całości):

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) { 
^

istnieją dwóch kandydatów. Jeden pod numerem main.cpp:6:3 (wiersz 6, znak 3) i jeden pod numerem algorithm:2579:1 (wiersz 2579, znak 1).

Jeden z nich napisał, a jeden z nich w #include <algorithm>.

Jeden z plików nagłówkowych zawiera <algorithm> bez pytania. Standardowe nagłówki mogą to robić, jak czasami denerwują.

W <algorithm> znajduje się szablon funkcyjny . Ponieważ std::string jest instancją klasy szablonów w namespace std, szablon funkcji std::min znajduje się w procesie zwanym "wyszukiwaniem zależnym od argumentu" lub "sprawdzeniem Koeniga". (kandydaci na przeciążenie funkcji są wyszukiwane lokalnie, a także w przestrzeni nazw argumentów funkcji, oraz w przestrzeni nazw argumentów szablonu dla argumentów funkcji oraz w przestrzeniach nazw rzeczy wskazywanych przez argumenty funkcja, itp.)

Twoja lokalna funkcja min również została znaleziona, ponieważ znajduje się w tej samej przestrzeni nazw co treść main.

Oba są równie dobrze dopasowane, a kompilator nie może zdecydować, do którego chce się zadzwonić. Więc generuje błąd informujący o tym.

Zarówno gcc, jak i clang mają error:, a następnie sekwencję note: s. Zwykle wszystkie s po błędzie są ważne dla zrozumienia błędu.

Aby rozwiązać ten problem, spróbuj dzwoniąc ::min (w pełni rozmowę kwalifikacyjna) lub zmiana nazwy funkcji do czegoś innego, lub dokonać wersja lepsze dopasowanie niż std::min (trudne, ale wykonalne w niektórych przypadkach), lub dzwoniąc (min)(a,b). Ostatni blokuje wyszukiwanie ADL/Koenig, a także blokuje rozszerzanie makr (na przykład, jeśli jakiś system operacyjny wstrzyknął do swoich nagłówków systemu makra #define min) (przez @ 0x499602D2).

+2

Lub wykonaj '(min) (a, b) ':) – 0x499602D2

+0

@ 0x499602D2: Dzięki, to działa. Ale jak to działa? Co to jest (min) (a, b)? – Destructor

+1

@meet '(min)' nie jest wyrażeniem wywołania funkcji, więc ADL nie będzie używane. – 0x499602D2

5

Występuje kolizja nazw z std::min. Prawdopodobnie jest on zawarty w jednym z innych standardowych nagłówków libary, które zawierasz, albo <iostream> lub <string>, przypuszczam, że to drugie. Szybka korekta polega na zmianie nazwy funkcji. Na przykład zmiana nazwy na mymin działa dobrze. Demo

+1

@Jeśli wystąpi kolizja. Nie napisałem przy użyciu przestrzeni nazw std; ? – Destructor

+2

Nie musisz, ponieważ 'std :: string' znajduje się w standardowej przestrzeni nazw biblioteki, to rozwiąże' std :: min' przez zależne od argumentu wyszukiwanie (ADL). – CoryKramer

+0

Wygląda na to, że '' '' get included from '' jeśli czytam tam błąd w prawo [tutaj] (http://coliru.stacked-crooked.com/a/189c75cb32ed7b58) – NathanOliver