Community
Participate
Working Groups
In the following code: template <typename T> void foo(T); template <typename T> void foo(T, typename T::type* = 0); int main() { foo(0); // ERROR HERE } the substitution of 'int' into the second overload causes a substitution error (because int::type is not well-formed) and should remove the candidate from the overload set. The call should therefore resolve unambiguously to the first overload. However, CDT gives the following error at the call site: 'foo' is ambiguous ' Candidates are: void foo(int, #0::type *) void foo(int) ' suggesting that it does not remove the second overload from the overload set.
Thanks, added testcase and fix.
OK, the test case above now works, but something slightly more complicated still fails: template <bool, typename _Tp = void> struct enable_if { }; template <typename _Tp> struct enable_if<true, _Tp> { typedef _Tp type; }; template <typename T, typename Signature> struct has_foo { template <typename U, U> struct type_check; template <typename X> static char (& chk(type_check<Signature, &X::foo> *))[1]; template <typename > static char (& chk(...))[2]; static bool const value = sizeof(chk<T>(0)) == 1; }; template <typename T> bool bar(T); template <typename T> bool bar(T, typename enable_if<has_foo<T, void(T::*)()>::value>::type* = 0); int main() { bar(0); // ERROR HERE: 'bar' is ambiguous } Here, has_foo<int, void(T::*)()>::value evaluates to false, and enable_if<false> does not have a nested 'type' member, so the substitution of 'int' into the second overload causes a substitution error, and so the second overload should be removed from the overload set.
Simplified testcase: template <bool, typename _Tp = void> struct enable_if { }; template <typename _Tp> struct enable_if<true, _Tp> { typedef _Tp type; }; template <typename T> struct has_foo { static bool const value = false; }; template <typename T> bool bar(T); template <typename T> bool bar(T, typename enable_if<has_foo<T>::value>::type* = 0); int main() { bar(); }
Sorry, please ignore the "simplified testcase" in the previous comment, it is wrong.
Please also ignore my description of why the substitution failure occurs in comment #2, that was incorrect too :( Here is a correct, and much more simplified, testcase: template <typename T> bool bar(T); template <typename T> bool bar(T, void(T::*)() = 0); int main() { bar(0); // ERROR HERE: 'bar' is ambiguous } Here, the substitution failure occurs because 'void(T::*)()' is ill-formed when T = int.
Thanks for the example! This is actually a different bug, for which it is usually better to open a new bug report. Added further testcase and fix.