为什么"decltype(i+j)"的结果不是右值引用?
Why is the result of "decltype(i+j)" not an rvalue reference?
我正在尝试为产生右值的操作提供一个简单的示例。
这个测试用例应该有效,但令人惊讶的是(对我来说),添加两个int
的结果不是右值(引用)。我在这里错过了什么?
void test(int i, int j)
{
// this assert should pass, but fails:
static_assert(std::is_same<decltype(i + j), int&&>(), "i + j should be a rvalue");
// this assert passed, but should fail:
static_assert(std::is_same<decltype(i + j), int>(), "this assert should fail...");
}
i + j
是一个 prvalue 表达式,
prvalue("纯右值")表达式是没有标识并且可以从中移动的表达式。
A + B、A % B、A& B、A <<B 以及所有其他内置算术表达式;
不是x值,
xvalue("过期值")表达式是具有标识并且可以从中移动的表达式。
并且 decltype 说明符产生 prvalue 的 T
,而不是 T&&
.
a) 如果表达式的值类别是 xvalue,则 decltype 产生 T&&;
b) 如果表达式的值类别是左值,则 decltype 产生 T&;
c) 如果表达式的值类别是 prvalue,则 decltype 产生 T。
你可以通过std::move
使其成为xvalue:
static_assert(std::is_same<decltype(std::move(i + j)), int&&>(), "std::move(i + j) is a xvalue then this static_assert won't fail");
根据@songyuanyao的回答,我注意到我的错误是检查错误的东西:我的目的是检查i+j
的结果是否会绑定到右值引用,但我检查了它是否是右值引用。
decltype 根据值类别推断类型,而不是基于值将绑定到的引用类型:
1)如果表达式的值类别为
xvalue
,则decltype得到T&&
;
2)如果表达式的值类别为lvalue
,则decltype得到T&
;
3)如果表达式的值类别为prvalue
,则decltype产生T
。
如列表中所示,自 C++11 以来,rvalues
在最低级别上不作为单独的类别存在。它们现在是一个包含prvalues
和xvalues
的复合类别。书面问题询问表达式是否为rvalue reference
并检查它是否为xvalue
。
从上面的列表中,很明显i+j
是一个 prvalue
,因此第三种情况适用。这就解释了为什么decltype(i + j)
是int
而不是int&&
。 xvalues
和 prvalues
都绑定到右值引用。
因此,通过检查i+j
是否绑定到lvalue reference
或rvalue reference
确认它确实绑定到rvalue reference
:
void foo(const int& f)
{
std::cout << "binds to lvalue reference" << std::endl;
}
void foo(int&& f)
{
std::cout << "binds to rvalue reference" << std::endl;
}
void test(int i, int j)
{
foo(i); // lvalue -> lvalue ref
foo(std::move(i)); // xvalue -> rvalue ref
// (std::move converts the argument to a rvalue reference and returns it as an xvalue)
foo(i + j); // prvalue -> rvalue ref
}
结论:i+j
不是右值引用,但它绑定到一个。
- 将对象数组的引用传递给函数
- decltype(1, t) 应该是 l 值引用吗?(编译器不同意)
- 如何使用 decltype 获取没有引用的指针?
- c++为什么decltype(*pointer)会产生引用
- 模板推导和 decltype(T) 如何在引用上工作?
- 使用 decltype(this) 获取函数引用
- 编译错误与迭代器取消引用的 decltype
- C++中容器的 decltype、通用引用和转发
- 为什么 decltype((i)) 是引用类型,而 decltype(i+0) 是 int 类型
- 如何从 decltype a 引用中获取值类型
- 删除 decltype 中的引用(返回 T 而不是 T&,其中 T& 是 decltype)
- 字符串的decltype和const引用返回类型
- 为什么"decltype(i+j)"的结果不是右值引用?
- 是否可以使函数模板从函数引用中获取“decltype”
- 对哪些表达式应用decltype后产生引用类型?< / h1 >
- 通过复制和decltype引用Lambda捕获
- 为什么decltype将变量定义为引用?
- 是成员声明`decltype(name)name;`在第一个名称引用封闭作用域的本地结构中允许
- Decltype (auto) foo()返回本地引用,没有任何警告
- 为什么decltype(a, b)被求值为引用