Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Temporary const array not binding to rvalue reference

I have the following test program:

#include <iostream>
#include <type_traits>
#include <utility>

template<typename Ty, std::size_t N>
void foo(Ty (&&)[N])
{
    std::cout << "Ty (&&)[" << N << "]\t" << std::is_const<Ty>::value << '\n';
}

template<typename Ty, std::size_t N>
void foo(Ty (&)[N])
{
    std::cout << "Ty (&)[" << N << "]\t" << std::is_const<Ty>::value << '\n';
}

template<typename Ty>
using id = Ty;

int main()
{
    std::cout.setf(std::cout.boolalpha);

    foo(id<int[]>{1, 2, 3, 4, 5});
    foo(id<int const[]>{1, 2, 3, 4, 5}); // <-- HERE.
    int xs[]{1, 2, 3, 4, 5};
    foo(xs);
    int const ys[]{1, 2, 3, 4, 5};
    foo(ys);
    foo(std::move(xs));
    foo(std::move(ys));
}

I would expect that the line marked with an arrow would call the rvalue overload like the non-const call just above it but it doesn't.

Is this just a bug in GCC or is there something in the standard that causes the lvalue overload to be selected?

like image 289
Simple Avatar asked Jul 07 '13 02:07

Simple


1 Answers

According to the standard §12.2 [class.temporary]:

Temporaries of class type are created in various contexts: binding a reference to a prvalue (8.5.3), returning a prvalue (6.6.3), a conversion that creates a prvalue (4.1, 5.2.9, 5.2.11, 5.4), throwing an exception (15.1), entering a handler (15.3), and in some initializations (8.5).

So id<int const[]>{1, 2, 3, 4, 5} is a temporary and therefore is an prvalue §3.10 [basic.lval]:

An rvalue (so called, historically, because rvalues could appear on the right-hand side of an assignment expression) is an xvalue, a temporary object (12.2) or subobject thereof, or a value that is not associated with an object.

A prvalue (“pure” rvalue) is an rvalue that is not an xvalue.

Hence shall be selected overloaded function with rvalue reference argument.

like image 140
A. Mikhaylov Avatar answered Nov 16 '22 01:11

A. Mikhaylov