https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85765

--- Comment #4 from Casey Carter <Casey at Carter dot net> ---
Narrowing the error down:

template<class T, class U = decltype(begin(declval<T&>())), decltype(*U(),0) =
0>
U g(T& t, long) { return begin(t); } // #1

----
prog.cc: In instantiation of 'U g(T&, long int) [with T = volatile il; U =
int*; decltype (((* U()), 0)) <anonymous> = 0]'

The "U = int*" is particularly damning here: it tells us the compiler
substituted `volatile il` into `decltype(begin(declval<T&>()))` to get
`begin(declval<volatile il&>())`. `int* begin(il);` is a *candidate* for
overload resolution - it has the right name and number of parameters - and it's
a viable candidate because the ICS from lvalue `volatile il` to `il` is an
identity conversion per [over.best.ics]/6: "Any difference in top-level
cv-qualification is subsumed by the initialization itself and does not
constitute a conversion. ... When the parameter has a class type and the
argument expression has the same type, the implicit conversion sequence is an
identity conversion." Since it's the *only* viable function, it is
unambiguously the *best* viable function.

So the only question here is why the compiler omits the final analysis that
would determine that initialization of an `il` from a `volatile il&` is
ill-formed - making the entire function call expression ill-formed - but only
does so when the following `decltype(*U(),0) = 0` is present in the template
parameter list.

Reply via email to