Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overload resolution with rvalue and lvalue reference candidates when passed empty initializer list

struct Foo {};
struct Bar {};

int Baz(const Foo&) { return 0; }
int Baz(Bar&&) { return 1; }

int main()
{
  return Baz({});
}

Is this call ambiguous? MSVC chooses the rvalue reference overload. GCC says it is ambiguous. Clang also chooses the rvalue reference but no longer if it's int Baz(std::vector<Bar>&&) instead or if Bar gets a constructor taking a std::initializer_list.

Is {} to Bar a standard conversion sequence?

Can someone explain why this does or does not apply:

  1. A standard conversion sequence S1 is better than a standard conversion sequence S2 if

[...]

c) or, if not that, both S1 and S2 are binding to a reference parameter to something other than the implicit object parameter of a ref-qualified member function, and S1 binds an rvalue reference to an rvalue while S2 binds an lvalue reference to an rvalue

(https://en.cppreference.com/w/cpp/language/overload_resolution)

like image 748
Stefan v.K. Avatar asked Jun 26 '20 17:06

Stefan v.K.


1 Answers

As it was already mentioned in the question, the standard says in [over.ics.rank]/(3.2):

Standard conversion sequence S1 is a better conversion sequence than standard conversion sequence S2 if

...

  • S1 and S2 are reference bindings (11.6.3) 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

...

So GCC is wrong here.

Actually Clang can be similarly deceived by adding default constructors in the structs:

struct Foo {
    constexpr Foo() = default;
};
struct Bar {
    constexpr Bar() = default;
};

constexpr int Baz(const Foo&) { return 0; }
constexpr int Baz(Bar&&) { return 1; }

int main() {
  static_assert( Baz({}) == 1 );
}

MSVC is the compiler that correctly selects Baz(Bar&&) overload here, demo: https://gcc.godbolt.org/z/sMcx9ro1x

like image 140
Fedor Avatar answered Oct 12 '22 13:10

Fedor