具有std :: minmax和rvalues的结构化绑定 [英] structured bindings with std::minmax and rvalues

查看:64
本文介绍了具有std :: minmax和rvalues的结构化绑定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在将 std :: minmax 与结构化绑定一起使用时,我遇到了一个相当微妙的错误。似乎传递的右值不会总是像人们期望的那样被复制。最初,我在自定义容器上使用了 T运算符[]()const ,但它与文字整数似乎相同。

I ran into a rather subtle bug when using std::minmax with structured bindings. It appears that passed rvalues will not always be copied as one might expect. Originally I was using a T operator[]() const on a custom container, but it seems to be the same with a literal integer.

#include <algorithm>
#include <cstdio>
#include <tuple>

int main()
{
    auto [amin, amax] = std::minmax(3, 6);
    printf("%d,%d\n", amin, amax); // undefined,undefined

    int bmin, bmax;
    std::tie(bmin, bmax) = std::minmax(3, 6);
    printf("%d,%d\n", bmin, bmax); // 3,6
}

使用GCC 8.1.1和 -O1 -Wuninitialized 将导致 0,0 打印为第一行,并且:

Using GCC 8.1.1 with -O1 -Wuninitialized will result in 0,0 being printed as first line and:

warning: ‘<anonymous>’ is used uninitialized in this function [-Wuninitialized]

-O2 时发出6.0.1的lang语也会给出错误的第一结果,而不会发出警告。

Clang 6.0.1 at -O2 will also give a wrong first result with no warning.

-O0 中,GCC给出了正确的结果,没有警告。对于clang,结果似乎正确为 -O1 -O0

At -O0 GCC gives a correct result and no warning. For clang the result appears to be correct at -O1 or -O0.

在右值仍可被复制的意义上,第一行和第二行是否不相等?

Should not the first and second line be equivalent in the sense that the rvalue is still valid for being copied?

为什么,这取决于优化级别?

Also, why does this depend on the optimization level? Particularly I was surprised that GCC issues no warning.

推荐答案

auto [amin, amax] 是将 auto auto& 等应用于生成的向上的对象 e ,它的返回值是 std :: minmax 初始化。本质上是这样的:

What's important to note in auto [amin, amax] is that the auto, auto& and so forth are applied on the made up object e that is initialized with the return value of std::minmax, which is a pair. It's essentially this:

auto e = std::minmax(3, 6);

auto&& amin = std::get<0>(e);
auto&& amax = std::get<1>(e);

amin 和<$的实际类型c $ c> amax 是引用任何 std :: get< 0> std :: get<的引用。该对对象返回1> 。他们自己返回对早已消失的对象的引用!

The actual types of amin and amax are references that refer to whatever std::get<0> and std::get<1> return for that pair object. And they themselves return references to objects long gone!

当您使用 std :: tie 时,您正在执行分配到现有对象(通过引用传递)。 rvalue的生存时间不必长于它们出现的赋值表达式。

When you use std::tie, you are doing assignment to existing objects (passed by reference). The rvalues don't need to live longer than the assignment expressions in which they come into being.

,则可以使用类似以下功能(而非生产质量)的功能:

As a work around, you can use something like this (not production quality) function:

template<typename T1, typename T2>
auto as_value(std::pair<T1, T2> in) {
    using U1 = std::decay_t<T1>;
    using U2 = std::decay_t<T2>;
    return std::pair<U1, U2>(in);
}

它可以确保货币对持有价值类型。像这样使用时:

It ensures the pair holds value types. When used like this:

auto [amin, amax] = as_value(std::minmax(3, 6));

我们现在获得了一个副本,结构化绑定引用了这些副本。

We now get a copy made, and the structured bindings refer to those copies.

这篇关于具有std :: minmax和rvalues的结构化绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆