有效c++第3项中的Scott说
将解密类型应用于名称的
生成该名称的声明类型。名称通常是lvalue表达式,但不影响解密类型的行为。然而,对于比名称更复杂的lvalue表达式,解密类型通常确保报告的类型是lvalue引用。也就是说,如果名称以外的lvalue表达式的类型为T,则解密类型报告为T&。这很少有任何影响,因为大多数lvalue表达式的类型本质上包括一个lvalue引用限定符。例如,返回lvalue的函数总是返回lvalue引用。
当他说函数返回lvalue时,意味着什么?例如,总是返回lvalue引用。
发布于 2020-11-16 17:14:35
它说的都是真的!
没有办法创建一个函数,因此它的返回类型不是T&,但是调用它会产生一个lvalue表达式。
每个其他的返回类型都会导致函数调用是一个rvalue表达式。
当您考虑到通过引用“返回”已经存在的东西的唯一方法时,这是很直观的--否则函数调用的结果总是“临时的”,不管是因为它在复制某个局部变量,还是因为它正在从某个局部变量中移动。
这个规则的可能例外,返回T&&,也不适用,因为它们产生rvalue表达式(这是移动语义工作的原因,因为只有rvalue表达式可以绑定到T&&参数)。
Scott报告了语言规则的一个结果,并告诉我们,同样的结果被用作decltype规则之一的理由。
可以说,他本可以这样说得更清楚:
是调用lvalue的唯一函数,是返回lvalue引用的函数。
发布于 2020-11-16 17:25:19
首先,我们不难想出一个lvalue表达式的例子,它也是一个名称:
int x{42};
x; // 'x' here is a name and an lvalue expression但是,什么不是名字呢?
例如,考虑
int f() {}这里调用的f()不是lvalue表达式。实际上,没有太多的东西不是名称,而是lvalue表达式,Scott只是对所有实际上是lvalue表达式而不是名称的事物表示,decltype报告的对应类型是lvalue引用类型。
#include <type_traits>
int f() { return 42; };
int& g() { static int g_x; return g_x; }
int main() {
int x;
int arr[3] = {1, 2, 3};
static_assert(
std::is_same_v<decltype(x), int>, "");
// ^ - 'x' is a name, and an lvalue
static_assert(
std::is_same_v<decltype(arr[1]), int&>, "");
// ^^^^^^ - 'arr[1]' is an lvalue expression
static_assert(
std::is_same_v<decltype((x)), int&>, "");
// ^^^ - '(x)' is an lvalue expression
static_assert(
std::is_same_v<decltype(f()), int>, "");
// ^^^ - 'f()' is not an lvalue
static_assert(
std::is_same_v<decltype(g()), int&>, "");
// ^^^ - 'g()' returns an lvalue
}发布于 2020-11-16 17:27:07
给予:
template<typename T> struct foo;
foo<decltype(*(int*)0)> x{};
int v;
foo<decltype(v)> y{};你得到:
error: variable ‘foo<int&> x’ has initializer but incomplete type
foo<decltype(*(int*)0)> x{};
^
error: variable ‘foo<int> y’ has initializer but incomplete type
foo<decltype(v)> y{};
^如您所见,decltype为取消引用的指针提供了int&,而为int变量v提供了int。
对于函数,他意味着返回lvalue的唯一方法是返回lvalue引用。
https://stackoverflow.com/questions/64862374
复制相似问题