我有以下测试程序:
#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));
}
我希望用箭头标记的行会调用rvalue重载,就像它上面的非const调用一样,但事实并非如此。
这只是GCC中的一个错误,还是标准中有一些导致选择左值超载的内容?
答案 0 :(得分:2)
根据标准§12.2 [class.temporary]
:
类类型的临时数在各种上下文中创建:绑定a 引用prvalue(8.5.3),返回prvalue(6.6.3),a 转换,创建一个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]
:
rvalue(历史上所谓的,因为rvalues可能出现在 赋值表达式的右侧是xvalue,a 临时对象(12.2)或其子对象,或不对应的值 与对象相关联。
prvalue(“纯”rvalue)是一个不是xvalue的右值。
因此应选择带有右值参考参数的重载函数。