为什么我得到 std::bad_variant_access 和 std::variant?

Why I'm getting std::bad_variant_access with std::variant?

考虑:

#include <variant>
#include <iostream>

int main()
{
    double foo = 666.666;
    std::variant<double, uint64_t> v = foo;
    std::cout << std::get<uint64_t>(v) << std::endl;
    return 0;
}

这导致:

terminate called after throwing an instance of 'std::bad_variant_access'
  what():  Unexpected index
Aborted (core dumped)

为什么?

我知道 std::variant 可以替代 union。但是,如果这种基本的东西失败了,它有什么好处?

I have understood that std::variant would be a replacement for union.

是的。有点儿。但是您的误解似乎与 C++ 中的联合有关。来自 cppreference:

It's undefined behavior to read from the member of the union that wasn't most recently written. Many compilers implement, as a non-standard language extension, the ability to read inactive members of a union.

请注意,这与 C 不同,这是导致 C++ 也允许访问非活动成员的常见误解的根本原因之一。

Why?

因为 std::variant 模仿联合但增加了一些安全性 std::get 是...

Index-based value accessor: If v.index() == I, returns a reference to the value stored in v. Otherwise, throws std::bad_variant_access. The call is ill-formed if I is not a valid index in the variant.

.

But if this kind of basic stuff fails what is it good for?

C++ 中的联合从来就不是这样使用的。当您想将两个或多个值压缩到同一内存中(但任何时候只使用其中一个)时,联合更节省内存。我从来没有遇到过他们的真实用例。然而,std::variant 是对 C++ 类型的一个很好的补充。更大的图景是,很久以来就存在所谓的产品类型,例如 std::pair<T1,T2>,从某种意义上说,它们可以表示的值集是 T1 x T2。使用 std::variant(和 std::any),现在 C++ 也有适当的(= 具有一定程度的类型安全性,你从未从联合中获得)总和类型,即 std::variant<T1,T2> 可以表示的值集是T1 + T2(抱歉使用草率的符号,希望它清楚)。

std::variant 是一个“类型安全的联合”,这意味着它会检查你从中得到的是最后存储在其中的类型。在此示例中,您正在存储 double 但试图获取 uint64_t.

在此处查看文档: https://en.cppreference.com/w/cpp/utility/variant/get

Type-based value accessor: If v holds the alternative T, returns a reference to the value stored in v. Otherwise, throws std::bad_variant_access. The call is ill-formed if T is not a unique element of Types....