通过参考存储的C 变体类成员
c++ variant class member stored by reference
我正在尝试尝试使用std ::变种。我正在存储一个std ::变体作为班级的成员。在以下代码中,如果变体是按值存储的,但如果vasector case和自定义对象不起作用,则情况正常,如果该变体是通过参考存储的。为什么是?
#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();
}
请参阅http://melpon.org/wandbox/permlink/vhnkanzhqgoyxu1h有关工作版本,以及http://melpon.org/melpon.org/wandbox/permlink/ppermlink/t5rcx0rcx0imtli4gk5e,该版本称为崩溃的版本:'std :: bad_variant_access' 什么():意外索引"
奇怪的是,当将代码的boost ::变体版本与成员一起存储为参考时,它可以按预期(打印向量尺寸= 3次两次)使用GCC7.0(请参阅此处http://melpon.org/wandbox/permlink/ew3bs1ing383vp6m)并且不起作用(在构造函数中打印vector size = 3,然后使用clang 4.0的vertent print()print()no crast)在clang 4.0(请参阅此处http://melpon.org)/wandbox/permlink/2grf2y8rprod7xdm)。
这很令人困惑。有人可以解释发生了什么吗?谢谢。
它不起作用,因为此语句A a1(simple);
创建了临时变体对象!
然后,您继续将该临时性绑定到您的const参考。但是,a1
结束后,临时性立即消失了范围,使您获得了悬空的参考。显然,创建副本可以工作,因为它始终涉及使用有效的副本。
可能的解决方案(如果始终复制您的担忧的性能)是接受变体对象旁程,然后将其移入您的本地副本中,例如:
explicit A(VectorOrSimple<int> arg) : member(std::move(arg)) {
print();
}
这将允许您的构造函数使用lvalues或rvalues调用。对于LVALUE,您的member
将通过移动源变体的副本来初始化,并且对于rvalues
,源的内容将仅移动两次。
变体是对象。它们包含一组类型之一,但不是其中一种类型。
对变体的引用是对变体对象的引用,而不是对包含类型之一的引用。
参考包装器的变体可能是您想要的:
template<class...Ts>
using variant_ref=std::variant<std::reference_wrapper<Ts>...>;
template<typename T>
using VectorOrSimple = std::variant<T, std::vector<T>>;
template<typename T>
using VectorOrSimpleRef = variant_ref<T, std::vector<T>>;
template<typename T>
using VectorOrSimpleConstRef = variant_ref<const T, const std::vector<T>>;
现在存储VectorOfSimpleConstRef<int>
。(不是const&
)。并将一个也在构造函数中。
还修改Print
通过const&
进行,以避免打印时不必要地复制std::vector
。
- C++错误消息*成员参考.**初学者*
- 当课程成员成员时,为什么参考会占据内存
- 参考数据成员到模板的实例化
- 如何调用成员初始化器列表中参考成员的构造函数
- 如果值来自成员变量,则复制初始化和参考初始化之间的C 差异
- 是否有一种方法可以始终通过值(制作副本)而不是在使用类成员函数时通过参考来传递
- 为什么合成的复制分配运算符被定义为如果类有参考成员,则将其定义为删除
- 为什么要为具有参考成员变量的类生成默认的复印件
- 参考的复制构造可以使用私有成员变量
- 通过名称或索引参考成员变量
- 不确定如何修复;非静态成员参考必须相对于特定对象
- 通过参考const成员通过参考时,尝试引用已删除的函数
- 成员函数返回成员变量的RVALUE参考
- 我如何在参考上使用数据成员而不使用新关键字创建对象
- 常量正确性和成员参考
- 参考成员函数调用
- sizeof参考对于类型和数据成员的不同
- 声明模板会员参考另一个类的模板成员数组
- 通过参考存储的C 变体类成员
- 参考类型静态数据成员的问题可能是编译器错误