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