我如何判断 std::variant 是否具有任何值?

Joe*_*Joe 6 c++ c++17 std-variant

std::variant我已经知道如何很好地使用std::get_if(),std::get()std::visit()。但是,如果我只是想要一种简单的方法来判断变体是否已初始化为任何值怎么办?也就是说,我不在乎值是什么,我只想要一个布尔测试。我怎么做?

例如,假设我在堆栈上声明一个变体:

std::variant<int, double> data;
Run Code Online (Sandbox Code Playgroud)

然后,我的函数继续运行,可能会也可能不会初始化该变量。在函数结束时,我想测试它是否已初始化。

  • 我看了一下这个index()函数。对于未初始化的变体和我初始化为声明的第一个类型的变体都返回 0 。
  • 我查看了该valueless_by_exception()函数,但无论我是否初始化变体,它都会返回 false。

我唯一能想到的是将它与默认构造的进行比较,如下所示:

using Data = std::variant<int, double>;

Data data;

// ... code here that might initialize data or might not...

if (data == Data())
    // Not initialized
else
    // Initialized
Run Code Online (Sandbox Code Playgroud)

这似乎有效,但阅读for的评论operator==()std::variant,似乎这种行为是未定义的。

那么,这是一种安全的测试方法,还是还有其他方法?

Sam*_*hik 13

std::variant<int, double> data;
Run Code Online (Sandbox Code Playgroud)

data已初始化。Astd::variant始终使用其值之一进行初始化,除非它是valueless_by_exception()

除非std::variant实例具有显式构造函数,否则第一个变体替代方案将被默认构造。这个特定的值data包含一个int默认构造的值。

如果第一个std::variant值没有默认构造函数,则变体不能默认构造,并且必须具有显式构造函数。

当需要有一个不“真正”(在空引号中包含“真正”一词)的变体概念时:通常的约定是作为std::monostate第一个变体值。这就是std::monostate目的。

std::variant<std::monostate, int, double> data;
Run Code Online (Sandbox Code Playgroud)

该变体是默认构造的并保存一个std::monostate值。它index()是 0。当您的变体索引为 0 时,您可以认为该变体未初始化,无论这对您的应用程序实际意味着什么。

本身并没有什么特别的std::monostate。这只是一个空班级。如果您访问具有价值的变体,std::monostate您的访问者需要处理std::monostate替代方案。


Ayx*_*xan 5

与任何需要单独的“无值”状态的东西一样,您可以使用std::optional

std::optional<std::variant<int, double>> data{}; // doesn't have a value
// ...
if (data.has_value()) {
   // ...
}
Run Code Online (Sandbox Code Playgroud)