https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53415
--- Comment #2 from Jonathan Wakely ---
(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
> 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::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::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::value> foo(X);
| ~~^