【发布时间】:2019-04-07 04:00:24
【问题描述】:
我想要一个变体,它可能包含类型 Foo、(不相交的)类型 Bar 或什么都没有。好吧,很自然,我在考虑使用std::variant<Foo, Bar, void> - 但这似乎不起作用。也就是说,您可以定义此类型,但如果您尝试实例化此类型,则会失败(GCC 8.2)。
那我用什么代替呢?某种空结构?
【问题讨论】:
标签: c++ c++17 variant monostate std-variant
我想要一个变体,它可能包含类型 Foo、(不相交的)类型 Bar 或什么都没有。好吧,很自然,我在考虑使用std::variant<Foo, Bar, void> - 但这似乎不起作用。也就是说,您可以定义此类型,但如果您尝试实例化此类型,则会失败(GCC 8.2)。
那我用什么代替呢?某种空结构?
【问题讨论】:
标签: c++ c++17 variant monostate std-variant
您真正想要的是具有 单个 可能值的替代类型 - 而不是 void,它具有 no 可能值(并且在其他方法)。换句话说:unit type 而不是bottom type。
作为<variant> 的一部分,标准库为此用例定义了一个“单元类型”:std::monostate(是的,它本质上是一个空结构)。使用它。
例子:
#include <variant>
using Foo = int;
using Bar = double;
int main() {
std::variant<std::monostate, Foo, Bar> v;
v = Foo{};
}
请注意,与问题不同,单可能值类型是 first 替代方案;即使Foo 不是,这也允许变量是默认可构造的。此外,以这种方式构造变体可能比构造 Foo 更便宜/更快,即使它是可默认构造的。
【讨论】:
struct { }; 作为void 的替代品并不是什么新鲜事。新的(对我来说)是它从 C++17 开始成为 std 库的一部分(如 std::monostate)。 ;-)
std::monostate 后感到惊讶。 “有或无”让我想起了std::optional,但我相信你的std::variant 的内存占用甚至更低(尽管这可能取决于实现细节)。
std::variant<std::monotone, T> 的内存占用低于std::optional<T>...
std::optional 的代码(出于好奇),我相信无论是否构建它,它都会存储在有效负载旁边(但这是不久前的事了——我可能会失败)。我假设,std::variant 不需要这样额外的“管理员”,是吗?出于好奇,我将 your std::variant<std::monostate, Foo, Bar> 与 my 替代 std::optional<std::variant<Foo, Bar> > 进行了比较,我不喜欢:Live Demo on coliru。 (我已经否认std 类的实现可能不同。)
std::variant 需要存储当前占用变体的类型的索引(并在异常情况下允许无类型)。