折叠表达式的值类别是否始终是 prvalue?
Is the value category of a fold expression always prvalue?
折叠表达式总是 prvalue 吗?这是对的吗?
template<typename... Args>
auto sum(Args... args) {
auto fold = (... + args);
return fold;
}
int main() {
sum(10, 2, 2);
}
我真的只对上面示例中(... + args)
的折叠表达式感兴趣。
折叠表达式与简单地写出运算符的 N - 1 个应用程序具有相同的语义(其中 N 是包中的元素数)。例如,sum(10, 2, 2)
将产生(10 + 2) + 2
.参见[温度变化]/9。
一般来说,这可能是也可能不是价值。用+
折叠 2 个或更多数值将始终产生一个 prvalue,因为内置的+
运算符会产生一个 prvalue,但如果包中只有一个元素args
,那么(... + args)
的意思与简单地通过其假设名称提及该元素的含义相同,因此结果将是一个左值。当然,您也可以与其他(可能过载的)运算符折叠,这可能会产生glvalue。
不必如此。这一切都取决于运营商。如果要改用+=
(有点人为的用法),则生成的表达式将不是 prvalue,而是左值。
澄清一下:
template<typename... Args>
auto sum(Args... args) {
auto fold = (... += args) = 3;
return fold;
}
由于+=
的结果是一个指定左操作数的左键(为了简单起见,我忽略了疯狂的重载),折叠表达式最终也会产生一个左键。所以最后的作业是完全有效的,虽然很臭。
折叠表达式不会影响表达式的值类别,它实际上只是编译器为您扩展参数包
template<typename... Args>
void foo(Args&... args)
{
(args, ...) = 42;
}
void bar()
{
int x, y, z;
foo(x, y, z);
}
有效,因为(args, ...)
具有类型int&
我真的很喜欢 @Brian 和 @Passer By 的答案; 它具有与使用运算符扩展参数包相同的语义。我想添加一个(人为的)示例来演示这意味着什么。
让我们先修改 sum 函数以使用decltype(auto)
和转发语义:
template<typename... Args>
decltype(auto) sum(Args&&... args) {
decltype(auto) fold = (... + std::forward<Args>(args));
return fold;
}
在功能上仍然相同,只是现在sum
将完全返回fold
的类型,并且fold
将采用求和的确切类型。
我们的折叠表达式称为一元左折叠,其扩展如下所示:
((E1opE 2) op ...) op EN
更具体地说,假设Args
可以被视为长度N
数组:
((Args[0] + Args[1]) + ...) + Args[N-1]
这基本上与
Args[0] + Args[1] + ... + Args[N-1]
因此,既然我们已经从整个事情中去除了一些神秘主义,那么不需要太多时间就能看到表达式的类型实际上只是将+
运算符两侧遇到的任何类型的结果相加的结果类型。
我可以设计以下具有一些奇怪的加法语义的Foo
类型:
const std::string global = "Global string";
struct Foo{
Foo(int){}
};
const std::string& operator +(const Foo&, const Foo&){
return global;
}
const std::string& operator +(const std::string& _str, const Foo&){
return _str;
}
现在,当我调用sum
以获取Foo
实例时,我将收到一个const std::string&
作为回报,这绝对不是 prvalue:
int main() {
std::cout << sum(Foo{10}, Foo{2}, Foo{2}) << std::endl;
}
指纹
全局字符串
- 在提升multi_index容器中,是否定义了"default index"?
- 在C++STL中是否有Polyval(Matlab函数)等价物?
- 检查输入是否不是整数或数字
- 是否可以初始化不可复制类型的成员变量(或基类)
- 在C++中,是否可以基于给定的标识符创建基类的新实例,反之亦然
- 是否可以通过C++扩展强制多个python进程共享同一内存
- 此代码是否违反一个定义规则
- 是否需要删除包含对象的"pair"?
- 是否可以从int转换为enum类类型
- 无论条件是否为true,if总是在c++中执行
- 如何找到大小'x'数组是否完全填充,在C++?
- 检查值是否在集合p1和p2中,但不在p3中
- 是否可以在编译时初始化数组,以便在运行时不会花费时间?
- 检查 std::shared_ptr<> 的当前底层类型是否为 T
- 返回指向对象的指针的函数调用是否为 prvalue?
- 一元*运算符的操作数是否期望一个 prvalue
- 我们如何测试是否可以使用 prvalue 调用某种类型的表达式
- 将非类非数组 prvalue 转换为符合 cv 条件的类型是否合法?
- 折叠表达式的值类别是否始终是 prvalue?
- 是否有任何用例 std::forward 带有 prvalue