https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53415
--- Comment #2 from Jonathan Wakely <redi at gcc dot gnu.org> --- (In reply to Nathan Ridge from comment #0) > 1. Template argument deduction/substitution is failing because of a > *warning*? The following reduced example: > > struct string > { > string(char*); > }; > > template <typename T> > void operator+(const string&, const T&); > > struct T > { > enum {value = 0}; > }; > > int main() > { > return 0 + T::value; > } > > gives a similar warning but no errors. It is inconsistent for an ambiguity > to cause just a warning in one case, and failure of template argument > deduction/substitution in another. That's by design. G++ extensions that change the meaning of ill-formed code are disabled in SFINAE contexts. This is similar to the -Wnarrowing option, for which the manual says: "Note that this does not affect the meaning of well-formed code; narrowing conversions are still considered ill-formed in SFINAE contexts." This ensures that static properties of the code (e.g. detectable using decltype or other compile-time metaprogramming) are consistent with other compilers that don't implement the same non-standard extension. > 2. There is no caret diagnostic associated with the "ISO C++ says that these > are ambiguous" warning, so it's difficult to tell what "these" are. (We can > infer from the candidates being operator+, but there could have been many > uses of operator+ in that expression, and only one of them ambiguous, so it > would be nice to have a caret pointing to that one). I can't reproduce this part of the report, I see a location for the ambiguity, with all versions I tested from 4.8.0 onwards: a.cc:19:5: warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second: [enabled by default] S<0 + T<X>::value> foo(X); ^ Since GCC 6 it's a range not a single location: a.cc:19:5: warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second: S<0 + T<X>::value> foo(X); ~~^~~~~~ And with current trunk the range is correct :-) a.cc:19:5: warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second: 19 | S<0 + T<X>::value> foo(X); | ~~^~~~~~~~~~~~~