https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104996
Bug ID: 104996 Summary: Overload resolution over rvalue/const lvalue array reference parameters for an init. list argument incorrectly picks the const lvalue ref. overload Product: gcc Version: 11.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: davveston at gmail dot com Target Milestone: --- GCC, MSVC and Clang all agrees and picks the rvalue overload for these two examples: #include <cstddef> // #g.1: rvalue reference function parameter constexpr bool g(int&&) { return true; } // #g.2: const lvalue reference function parameter constexpr bool g(int const&) { return false; } static_assert(g(0), ""); // OK: all compilers agree // #f.1: rvalue ref overload template<std::size_t size> constexpr bool f(int (&&)[size]) { return true; } // #f.2: lvalue ref overload template<std::size_t size> constexpr bool f(int const (&)[size]) { return false; } template<typename T> using type = T; static_assert(f(type<int[3]>{1, 2, 3})); // OK: all compilers agree. As expected, as per https://timsong-cpp.github.io/cppwp/n4868/over.ics.rank#3.2.3. However for a call to the `f` overloads with an initializer list argument GCC picks the lvalue ref overload #f.2 whereas Clang and MVSC picks the rvalue ref overload #f.1. Afaict Clang and MSVC are correct, as per https://timsong-cpp.github.io/cppwp/n4868/over.ics.list#9, particularly (albeit non-normative) covered by /Note 2. > Otherwise, if the parameter is a reference, see [over.ics.ref]. > > [Note 2: The rules in this subclause will apply **for initializing the > underlying temporary for the reference.** — end note] DEMO: https://godbolt.org/z/YbeKo4T1q