Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ambiguous call of overloaded template with parameter (const T&, const T&) or (const char (&)[N], const char (&)[M])

For the following code:

#include <iostream>
using std::cout; using std::endl;

template <typename T>
int compare(const T&, const T&) {
    cout << __PRETTY_FUNCTION__ << endl;
    return 0;
}
template <size_t N, size_t M>
int compare(const char (&)[N], const char (&)[M]) {
    cout << __PRETTY_FUNCTION__ << endl;
    return 0;
}

int main(int argc, char *argv[]) {
    compare("hi", "is");
}

When I compiles the code with g++ -std=c++1y, it complains:

error: call of overloaded ‘compare(const char [3], const char [3])’ is ambiguous
     compare("hi", "is");

According to the rules of template overloading, viable functions are:

compare(const T&, const T&) with T = char [3]
compare(const char (&)[N], const char (&)[M]) with N = 3ul, M = 3ul

They both provide an equally good (i.e., exact) match to the call. So I should check which one is more specialized.

But according to my limited knowledge, const T& is more general than const char (&)[N]. So I think that compare(const char (&)[N], const char (&)[M]) is more specialized. But why is this call ambiguous?

like image 747
zhenguoli Avatar asked Sep 24 '17 11:09

zhenguoli


1 Answers

The first overload compare(const T&, const T&) forces both parameters to be the same type, while the second overload doesn't. So in this regard the first overload is more specific.

However, the second overload forces both parameters to be char arrays, so it is more specific in that regard.

Therefore, neither overload can be said to be more specialized than the other, and the result is the ambiguity error.

Another way to look at it is that each overload can accept an input that the other doesn't: Only the first overload will accept a call where both arguments are int&. And only the second overload will accept a call where the arguments are char (&)[2] and char (&)[3].

If you change the second overload to

template <size_t N> int compare(const char (&)[N], const char (&)[N])

it will fix the error, as this is now strictly more specific than the first overload.

like image 148
interjay Avatar answered Sep 26 '22 14:09

interjay