https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86430
Bug ID: 86430 Summary: ambiguous overload? Product: gcc Version: 8.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: zhonghao at pku dot org.cn Target Milestone: --- The code is as follow: // snip template<typename T> struct Const { typedef void const type; }; template<typename T> void f(T, typename Const<T>::type*) { } // T1 template<typename T> void f(T, void const *) { } // T2 int main() { void *p = 0; f(0, p); } // snap g++ produces the following errors: error: call of overloaded 'f(int, void*&)' is ambiguous int main() { void *p = 0; f(0, p); } I tried clang++. It accepts the above code. My understanding is as follows: template<typename T> void f(T, typename Const<T>::type*) // T1 template<typename T> void f(T, void const *) // T2 We're going to deduce (unique-1, Const<unique-1>::type*) -> (T, void const*) // T1 -> T2 and (unique-1, void const*) -> (T, Const<T>::type*) // T2 -> T1 The first one takes T = unique-1 but fails at matching "void const*" to "Const<unique-1>::type*". So this round fails for the second parameter. The second one takes T = unique-1. The second is a non-deduced context, thus not compared, and this does not mismatch. So this round succeeds for parameter 2. So we have: For parameter 1, each template is at least as specialized as the other one. For parameter 2, T1 -> T2 did not succeed, so T1 is not at least as specialized as T2 - but not vice versa (T2 -> T1 suceeded). Thus for parameter 2, T2 is more specialized. It follows that T2 overall is more specialized that T1. As a result, the overload is not ambiguous. Please correct me, if I am wrong.