10

我有以下测试程序:

#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 中的一个错误,还是标准中的某些内容导致选择左值重载?

4

1 回答 1

2

根据标准§12.2 [class.temporary]

类类型的临时对象是在各种上下文中创建的:将引用绑定到纯右值 (8.5.3)、返回纯右值 (6.6.3)、创建纯右值的转换 (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]

右值(历史上称为右值,因为右值可能出现在赋值表达式的右侧)是一个 xvalue、一个临时对象 (12.2) 或其子对象,或者一个与对象无关的值。

prvalue(“纯”右值)是不是 xvalue 的右值。

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

于 2013-07-14T08:15:52.620 回答