问题标签 [std-variant]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
1138 浏览

c++ - 对于 boost::variant,是否有类似 std::visit 的 boost::visit?

使用 C++14,我将boost::variant其用作编译时多态性的一种方式:

这两个类都有一个方法sayHello()。我想打电话:

我知道static_visitor方法,但我觉得它很麻烦。有没有我想念的boost::visit那种std::visit?如果没有,为什么不存在?

这里的最小例子。

0 投票
0 回答
251 浏览

c++17 - boost::mpi 和 boost:serialization 与 std::variant

c++17 引入了新类型std::variant. 是否可以定义一个序列化例程,以便与std::variant结合使用boost::mpi

例如,考虑一个简单的程序

它不编译给出错误

如何正确定义 a 的serialize成员std::variant?请注意,在上面的示例中,这两种类型A都有B一个正确定义的序列化成员。

0 投票
1 回答
154 浏览

c++ - 无法通过变体获取列表中元素的地址

我试图循环一个列表并获取元素的地址。但是在使用变体类时,所有元素的地址都是相同的。

当你##标题##

看起来变体标准库无法获取原始变量自己的地址。因此,每次我尝试遍历链表时,母链表中所有元素的地址都会改变。因此,对于母链表中的那些链表,我只能显示,不能回推。我的一位朋友告诉我,c++ 完全是关于指针的,他讨厌 Java,因为它确实有指针!现在我不能在这个库中使用 c++ 中的指针。我听说这个问题可以通过 boot:: variant、std:: optional 或多态来解决。但我不知道这些是如何工作的。不管怎样,有人说这个库之所以没有触及地址的想法是因为他们对如何赋值存在分歧

0 投票
1 回答
926 浏览

c++ - 如何根据枚举参数返回不同的类型

我有两个需要以下功能的功能:

功能1:需要一个变量的地址来设置值。(它知道正确的类型)

函数 2:是一个需要类型值的重载函数。

我需要一种基于枚举(指定要使用的类型)返回不同类型的方法。

我尝试使用 std::get ,因为您可以使用数字来指定类型。但是,它要求 SelectedType 是一个常量表达式,而事实并非如此。

关键是使用一个变量来避免代码重复。

考虑以下代码:

0 投票
2 回答
97 浏览

c++ - 为什么 std::variant 用开始和结束迭代器编译?

似乎编译器应该能够捕捉到 std::variant 没有迭代器方法的事实,但似乎我的代码编译没有问题(即使我为变体随机组成方法或成员变量),但它在运行时崩溃(理所当然)。有人可以解释为什么这段代码会编译吗?

注意:这不会阻碍进度,因为现在我正在使用 std::visit,但很高兴知道为什么要编译。

我尝试过使用不同的变体模式,它们都可以编译。请参阅代码示例。您可以将其弹出到 cppreferences 或 Godbolt 中,它应该使用 C++17 标志或更高版本进行编译

我最初的案例是使用地图,但它可以有效地与任何东西一起编译。此外,我可以随机将 begin() 替换为任何其他单词,它仍然可以编译。我知道这样做的正确方法是访问。我不可避免地试图拥有一个处理地图和多地图并将其转换为另一种数据结构的函数。

谢谢!

0 投票
1 回答
156 浏览

c++ - 如何将当前替代类型的 std::variant 传递给可调用对象?

我正在使用在运行时确定的参数调用一些用户定义的可调用对象。我有以下工作:

这一切都可以正常工作,但是,argument_t必须是用户定义函数中所有参数的类型才能成功工作。

我试图弄清楚如何改为传递当前替代类型的变体。

就像是

但显然这不起作用......不幸的是,我在这方面的技能已经结束。

如何才能做到这一点?

0 投票
3 回答
628 浏览

c++ - std::optional 如何永远不会“异常无价值”?

std::variant可以进入一种叫做“异常无价值”的状态。

据我了解,这种情况的常见原因是移动分配引发异常。变体的旧值不再保证存在,预期的新值也不再存在。

std::optional但是,没有这样的状态。cppreference 提出了大胆的主张:

如果抛出异常,*this ... 的初始化状态不变,即如果对象包含一个值,它仍然包含一个值,反之亦然。

如何std::optional能够避免成为“异常无价值”,而std::variant不是?

0 投票
0 回答
3266 浏览

ios - 命名空间“std”中没有名为“variant”的模板

在 XCode 10.3 中,当我尝试构建时收到错误消息 -> 在命名空间“std”中没有名为“variant”的模板

对于代码行->

在构建设置中,我尝试将 C++ 语言方言和 C++ 标准库设置为不同的值,包括 C++ 17,但无济于事。这在早期版本的 XCode 中有效,并且代码和项目没有改变,所以我不确定为什么这不起作用?它还可以找到变体头文件。

0 投票
4 回答
612 浏览

c++ - std::bind 到包含多个 std::function 类型的 std::variant

我正在玩回调函数,并希望通过std::bind签名不同的方式注册多个函数(尽管它们都返回void)。将 的结果分配给“转换为非标量类型”错误中std::bind的产量。std::variant是歧义错误吗?我可以向编译器提供更多信息吗?

删除std::bind(允许分配)不是一个选项,因为我希望使用一些注册回调


例如:

有效,但是

没有,虽然我希望它编译成一个std::variant包含std::function<void()>.

我在 GCC 7.4.0 中收到以下编译错误-std=c++17

0 投票
3 回答
11851 浏览

c++ - `std::variant` vs. 继承 vs. 其他方式(性能)

我想知道std::variant性能。我什么时候不应该使用它?看起来虚函数仍然比使用std::visit这让我感到惊讶的要好得多!

在“A Tour of C++”中,Bjarne Stroustruppattern checking在解释std::holds_alternativesoverloaded方法后这样说:

这基本上相当于一个虚函数调用,但可能更快。与所有性能声明一样,当性能至关重要时,应该通过测量来验证这种“可能更快”。对于大多数用途,性能差异是微不足道的。

我已经对我想到的一些方法进行了基准测试,结果如下:

基准 http://quick-bench.com/N35RRw_IFO74ZihFbtMu4BIKCJg

如果你开启优化,你会得到不同的结果:

启用 op 的基准测试

http://quick-bench.com/p6KIUtRxZdHJeiFiGI8gjbOumoc

这是我用于基准测试的代码;我确信有更好的方法来实现和使用变体来使用它们而不是虚拟关键字(继承与 std::variant):

删除旧代码;看看更新

谁能解释一下实现这个用例的最佳方法是什么std::variant让我进行测试和基准测试:

我目前正在实现RFC 3986,它是“URI”,对于我的用例,这个类将更多地用作 const,可能不会有太多改变,用户更有可能使用这个类来查找每个特定的URI 的一部分,而不是制作一个 URI;std::string_view因此使用而不是单独分隔 URI 的每个段是有意义的std::string。问题是我需要为它实现两个类;当我只需要一个 const 版本时;另一个用于当用户想要创建 URI 而不是提供一个并通过它进行搜索时。

所以我用 atemplate来修复它自己的问题;但后来我意识到我可以使用std::variant<std::string, std::string_view>(或者也许std::variant<CustomStructHoldingAllThePieces, std::string_view>);所以我开始研究看看它是否真的有助于使用变体。从这些结果来看,这似乎是使用继承,virtual如果我不想实现两个不同的const_uriuri类,这是我最好的选择。

你觉得我应该怎么做?


更新 (2)

感谢@gan_ 在我的基准代码中提到并修复了提升问题。 http://quick-bench.com/Mcclomh03nu8nDCgT3T302xKnXY基准

我对 try-catch hell 的结果感到惊讶,但感谢这个现在有意义的评论。

更新 (3)

我删除了该try-catch方法,因为它非常糟糕;并且还随机更改了选定的值,从外观上看,我看到了更现实的基准。virtual毕竟 这似乎不是正确的答案。http://quick-bench.com/o92Yrt0tmqTdcvufmIpu_fIfHt0随机访问

http://quick-bench.com/FFbe3bsIpdFsmgKfm94xGNFKVKs(没有内存泄漏哈哈)

更新 (4)

我消除了生成随机数的开销(我在上次更新中已经这样做了,但似乎我为基准获取了错误的 URL)并添加了一个 EmptyRandom 以了解生成随机数的基线。并且还在 Virtual 中做了一些小的改动,但我认为它不会影响任何东西。 http://quick-bench.com/EmhM-S-xoA0LABYK6yrMyBb8UeI空随机添加

http://quick-bench.com/5hBZprSRIRGuDaBZ_wj0cOwnNhw(删除了虚拟,以便您可以更好地比较其余部分)


更新 (5)

正如 Jorge Bellon在评论中所说,我没有考虑分配成本;所以我将每个基准转换为使用指针。这种间接性当然会对性能产生影响,但现在更公平了。所以现在循环中没有分配。

这是代码:

删除旧代码;看看更新

到目前为止,我运行了一些基准测试。似乎 g++ 在优化代码方面做得更好:

对于铿锵声:

现在,对于 clang,最好使用虚拟继承,但对于 g++,最好使用holds_alternative,或者get_if但总的来说,std::visit到目前为止,对于我的几乎所有基准测试来说,这似乎都不是一个好的选择。

我认为如果将模式匹配(能够检查除整数文字之外的更多内容的 switch 语句)添加到 c++ 中将是一个好主意,我们将编写更清洁和更可维护的代码。

我想知道package.index()结果。不应该更快吗?它有什么作用?

Clang 版本:http: //quick-bench.com/cl0HFmUes2GCSE1w04qt4Rqj6aI

使用One one而不是auto one = new One基于Maxim Egorushkin 的评论的版本:http : //quick-bench.com/KAeT00__i2zbmpmUHDutAfiD6-Q(没有太大改变结果)


更新 (6)

我做了一些更改,结果现在从编译器到编译器有很大不同。但这似乎是最好的解决方案std::get_if。由于未知原因,现在似乎在 clang 中效果最好。这真的让我感到惊讶,因为我记得在 gcc 中做得更好。而且完全没有竞争力;在最后一个基准测试中,它甚至比 vtable 查找还要糟糕。std::holds_alternativesvirtualvirtualstd::visit

这是基准(使用 GCC/Clang 以及 libstdc++ 和 libc++ 运行它):

http://quick-bench.com/LhdP-9y6CqwGxB-WtDlbG27o_5Y

GCC 编译器的结果:

clang 编译器的结果(我对此感到惊讶):


迄今为止的最佳基准(将更新):http: //quick-bench.com/LhdP-9y6CqwGxB-WtDlbG27o_5Y(也可以查看 GCC)