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

--- Comment #3 from Harald van Dijk <harald at gigawatt dot nl> ---
(In reply to Jonathan Wakely from comment #1)
> The template constructor allows s({1, 2, 3}) to mean s(S2{1,2,3}) which
> tries to use the deleted copy constructor.

Thanks, I think you're right about that. The diagnostic didn't help me
understand what was going on, but now that I do understand it, I do not see how
it could be improved.

But all other things equal, aren't rvalue reference overloads preferred over
lvalue reference overloads, so shouldn't S1 && still be preferred over const S2
&? That appears to be the logic Intel is using, and in a similar example,

  struct S1 {};
  struct S2 {};
  void f(const S1 &);
  void f(S2 &&);
  void g() { f({}); }

clang does agree that this calls f(S2 &&) as well, but GCC still rejects it as
ambiguous.

The relevant bit in the standard seems to be [over.ics.rank]p3.2.3
<http://eel.is/c++draft/over.ics.rank#3.2.3>: (yes, I know it's a draft, but
this text is also present in the actual standard)

> - Standard conversion sequence S1 is a better conversion sequence than 
> standard conversion sequence S2 if
> [...]
>   - S1 and S2 are reference bindings and neither refers to an implicit object 
> parameter of a non-static member function declared without a ref-qualifier, 
> and S1 binds an rvalue reference to an rvalue and S2 binds an lvalue reference

This appears to not just disambiguate between lvalue and rvalue references to
the same type, it also disambiguates between lvalue and rvalue references to
different types.

Reply via email to