2

考虑:

#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。但是,如果这种基本的东西失败了,它有什么用呢?

4

2 回答 2

6

我知道 std::variant 将替代联合。

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

从最近未写入的联合成员中读取是未定义的行为。许多编译器作为非标准语言扩展实现了读取联合的非活动成员的能力。

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

为什么?

因为std::variant模仿工会但增加了一些安全性并且std::get......

基于索引的值访问器:如果 v.index() == I,则返回对存储在 v 中的值的引用。否则,抛出 std::bad_variant_access。如果 I 不是变体中的有效索引,则调用格式错误。

.

但是,如果这种基本的东西失败了,它有什么用呢?

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

于 2020-04-15T14:17:52.507 回答
1

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

请参阅此处的文档: https ://en.cppreference.com/w/cpp/utility/variant/get

基于类型的值访问器:如果 v 持有替代 T,则返回对存储在 v 中的值的引用。否则,抛出 std::bad_variant_access。如果 T 不是 Types 的唯一元素,则该调用格式不正确。...

于 2020-04-15T14:18:03.193 回答