gre*_*reg 1 c++ boost variant c++17
我正在尝试使用std :: variant.我将std :: variant存储为类的成员.在下面的代码中,如果变量按值存储,则工作正常,但如果变量通过引用存储,则不起作用(对于矢量大小写,也适用于自定义对象).这是为什么?
#include <variant>
#include <vector>
#include <iostream>
template<typename T>
using VectorOrSimple = std::variant<T, std::vector<T>>;
struct Print {
void operator()(int v) { std::cout << "type = int, value = " << v << "\n"; }
void operator()(std::vector<int> v) const { std::cout << "type = vector<int>, size = " << v.size() << "\n"; }
};
class A {
public:
explicit A(const VectorOrSimple<int>& arg) : member(arg) {
print();
}
inline void print() const {
visit(Print{}, member);
}
private:
const VectorOrSimple<int> member; // const VectorOrSimple<int>& member; => does not work
};
int main() {
int simple = 1;
A a1(simple);
a1.print();
std::vector<int> vector(3, 1);
A a2(vector);
a2.print();
}
Run Code Online (Sandbox Code Playgroud)
见http://melpon.org/wandbox/permlink/vhnkAnZhqgoYxU1H一个工作版本,并http://melpon.org/wandbox/permlink/T5RCx0ImTLi4gk5e与错误崩溃的版本:"扔"STD的一个实例后终止叫:: bad_variant_access'what():意外索引"
奇怪的是,当编写一个boost :: variant版本的代码并将该成员存储为引用时,它可以按预期工作(使用gcc7.0打印矢量大小= 3两次)(请参阅此处http://melpon.org/wandbox/ permlink/eW3Bs1InG383vp6M)并不起作用(在构造函数中打印向量大小= 3,然后在随后的print()调用中向量大小= 0,但没有崩溃)与clang 4.0(请参阅http://melpon.org/wandbox/) permlink/2GRf2y8RproD7XDM).
这很令人困惑.有人可以解释发生了什么吗?谢谢.
它不起作用,因为此语句A a1(simple);
创建临时变体对象!
然后,继续将所述临时绑定到const引用.但是在施工结束后临时超出范围a1
,留下你的悬挂参考.显然,创建副本很有用,因为它总是涉及使用有效副本.
一个可能的解决方案(如果总是复制的性能让你担心)是接受变量对象的值,然后将其移动到本地副本,如下所示:
explicit A(VectorOrSimple<int> arg) : member(std::move(arg)) {
print();
}
Run Code Online (Sandbox Code Playgroud)
这将允许使用左值或右值调用构造函数.对于左值,您member
将通过移动源变体的副本来初始化,并且源rvalues
的内容将被移动(最多)两次.