2015-05-15 16 views
11

Ich bin nicht vertraut mit Vorlagen. Ich habe gerade angefangen es zu lernen. Warum bekomme ich Fehler im Folgeprogramm?Vorlage Funktion Anruf Mehrdeutigkeit Fehler

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

Fehler:

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

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

Bitte helfen Sie mir.

+1

Welchen Compiler benutzen Sie? Es wäre Naht Ihre '' hat eine Min-Funktion definiert. – NathanOliver

+0

Ich habe die Klasse umbenannt und es funktioniert gut (http://ideone.com/ygVUcr). Nicht sicher, warum 'min' mit' std :: min' in Konflikt steht. – Mahesh

+0

@Mahesh: Haben Sie das Problem reproduziert, ohne es umzubenennen? –

Antwort

14

Es gibt hier zwei Dinge.

Ihr erstes Problem ist, dass Sie nur einen Teil der Fehlermeldung enthalten. Here is a link to the code being complied in gcc and clang, und eine der resultierenden Fehlermeldungen (vollständig):

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

gibt es zwei Kandidaten. Eine bei main.cpp:6:3 (Zeile 6, Zeichen 3) und eine bei algorithm:2579:1 (Zeile 2579, Zeichen 1).

Einer von Ihnen schrieb, und einer von ihnen in #include <algorithm>.

Eine Ihrer Header-Dateien enthalten <algorithm>, ohne dass Sie darum bitten. Die Standard-Header können dies tun, so nervig wie es manchmal ist.

In <algorithm> gibt es eine std::min Funktionsvorlage. Da std::string eine Instanz einer Vorlagenklasse in namespace std ist, wird die Funktionsvorlage std::min über einen Prozess namens "argumentabhängiges Nachschlagen" oder "Koenig-Nachschlagen" gefunden. (Funktionsüberladungskandidaten werden lokal gesucht, ebenso in den Namespaces der Argumente für die Funktion und in den Namespaces der Template - Argumente zu den Argumenten der Funktion, und in den Namespaces der Dinge, auf die die Argumente der Funktion, etc.)

Ihre lokale Funktion min wird ebenfalls gefunden, da sie sich im selben Namensraum befindet wie der Körper main.

Beide sind gleich gute Übereinstimmungen, und der Compiler kann nicht entscheiden, welchen Sie aufrufen möchten. Es erzeugt also einen Fehler, der dir das sagt.

Sowohl gcc und clang tun error: dann eine Sequenz von note: s. Normalerweise alle der note: s nach einem Fehler sind wichtig, um den Fehler zu verstehen.

Um dies zu beheben, versuchen ::min Aufruf (voll den Aufruf der Qualifikation) oder die Funktion etwas anderes umbenennen oder Ihre Version machen ein besseres Spiel als std::min (schwierig, aber machbar in einigen Fällen) oder (min)(a,b) aufrufen. Der letzte blockiert ADL/Koenig-Lookup und blockiert auch die Makroerweiterung (zum Beispiel, wenn einige OS #define min Makros in ihre System-Header eingefügt haben) (via @ 0x499602D2).

+2

Oder Do' (min) (a, b) ':) – 0x499602D2

+0

@ 0x499602D2: Danke, es funktioniert. Aber wie funktioniert es? Was bedeutet (min) (a, b)? – Destructor

+1

@meet '(min)' ist kein Funktionsaufruf, daher wird ADL nicht verwendet. – 0x499602D2

5

Sie stoßen auf eine Namenskollision mit std::min. Es ist wahrscheinlich in einem der anderen Standard-Bibliothek Header enthalten, entweder <iostream> oder <string>, meine Vermutung ist wahrscheinlich der letztere. Die schnelle Lösung besteht darin, Ihre Funktion umzubenennen. Beispielsweise funktioniert das Umbenennen in mymin einwandfrei. Demo

+1

@ Aber wie Kollision auftritt. Ich habe nicht mit namespace std geschrieben; ? – Destructor

+2

Sie müssen nicht, da 'std :: string' im Standard-Bibliotheksnamensraum ist, wird' std :: min' über die argumentabhängige Suche (ADL) aufgelöst. – CoryKramer

+0

Es sieht aus wie '' von '' 'wenn ich dort lesen Fehler Recht [hier] (http://coliru.stacked-crooked.com/a/189c75cb32ed7b58) – NathanOliver