Template function call ambiguity error
Asked Answered
A

2

13

I am not familiar with templates. I've just started learning it. Why I am getting errors in following program?

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

Errors:

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

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

Please help me.

Ascidian answered 15/5, 2015 at 17:4 Comment(5)
What compiler are you using? It would seam your <string> has a min function defined in it.Booster
I renamed the class and it executes fine (ideone.com/ygVUcr). Not sure why min is conflicting with std::min.Mcclish
@Mahesh: Did you reproduce the problem without renaming it?Blenny
Rename your min function for an easier life!Customs
@meet If you are using Visual Studio, there is an option called Show Includes in compilation settings. That should give you an idea of all headers included in the program.Mcclish
S
16

There are a two things going on here.

Your first problem is that you only included part of the error message. Here is a link to the code being complied in gcc and clang, and one of the resulting error messages (in full):

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

there are two candidates. One at main.cpp:6:3 (line 6, character 3) and one at algorithm:2579:1 (line 2579, character 1).

One of them you wrote, and one of them in #include <algorithm>.

One of your header files included <algorithm> without you asking for it. The standard headers are allowed to do this, as annoying as it is sometimes.

In <algorithm> there is a std::min function template. As std::string is an instance of a template class in namespace std, the function template std::min is found via a process called "argument dependent lookup" or "Koenig lookup". (function overload candidates are searched for locally, and also in the namespaces of the arguments to the function, and in the namespaces of the template arguments to the arguments to the function, and in the namespaces of the things pointed to by the arguments of the function, etc.)

Your local function min is also found, as it is in the same namespace as the body of main.

Both are equally good matches, and the compiler cannot decide which one you want to call. So it generates an error telling you this.

Both gcc and clang do error: then a sequence of note:s. Usually all of the note:s after an error are important to understanding the error.

To fix this, try calling ::min (fully qualifying the call), or renaming the function to something else, or make your version a better match than std::min (tricky, but doable in some cases), or calling (min)(a,b). The last blocks ADL/Koenig lookup, and also blocks macro expansion (for example, if some OS has injected #define min macros into their system headers) (via @ 0x499602D2).

Synchro answered 15/5, 2015 at 17:14 Comment(3)
Or do (min)(a,b) :)Singultus
@0x499602D2: Thanks, it works. But how it works? What is meaning of (min)(a,b)?Ascidian
@meet (min) is not a function call expression so ADL will not be used.Singultus
P
5

You're running into a name collision with std::min. It is likely included in one of the other standard libary headers that you included, either <iostream> or <string>, my guess is probably the latter. The quick fix is to rename your function. For example, renaming it to mymin works fine. Demo

Pressure answered 15/5, 2015 at 17:14 Comment(3)
@But how collision occurs. I haven't written using namespace std; ?Ascidian
You don't need to, since std::string is in the standard library namespace, it will resolve std::min via argument dependent lookup (ADL).Pressure
It looks like <algorithm> get included from <iostream> if I am reading there error right hereBooster

© 2022 - 2024 — McMap. All rights reserved.