临时常量数组未绑定到右值引用

Temporary const array not binding to rvalue reference

本文关键字:引用 绑定 常量 数组      更新时间:2023-10-16

我有以下测试程序:

#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));
}

我希望用箭头标记的行会调用右值重载,就像它上面的非常量调用一样,但它没有。

这只是GCC中的一个错误,还是标准中有什么东西导致选择左值重载?

根据标准§12.2 [class.temporary]:

类类型的临时性是在各种上下文中创建的:绑定引用prvalue(8.5.3),返回prvalue(6.6.3)创建prvalue(4.1、5.2.9、5.2.11、5.4)的转换,抛出一个异常(15.1),输入一个处理程序(15.3),在某些情况下初始化(8.5)。

因此id<int const[]>{1, 2, 3, 4, 5}是临时的,因此是一个prvalue §3.10 [basic.lval]:

右值(历史上之所以这么叫,是因为右值可能出现在赋值表达式的右侧)是一个x值临时对象(12.2)或其子对象,或不是与对象关联。

prvalue("纯"右值)是一个不是xvalue的右值。

因此,应选择带有右值引用参数的重载函数。