C++ 将联合用作树中的项类型,以便存储两种不同的数据类型 请考虑以下代码: union tree_item { tree_item(std::valarray<double> const& point) : point(point) { } tree_item(unsigned coord, double coord_value) : splitting_line({ coord, coord_value }) { } struct { unsigned coord; double coord_value; } splitting_line; std::valarray<double> point; };
但我假设,如果我们给C++ 将联合用作树中的项类型,以便存储两种不同的数据类型 请考虑以下代码: union tree_item { tree_item(std::valarray<double> const& point) : point(point) { } tree_item(unsigned coord, double coord_value) : splitting_line({ coord, coord_value }) { } struct { unsigned coord; double coord_value; } splitting_line; std::valarray<double> point; };,c++,c++11,c++14,C++,C++11,C++14,但我假设,如果我们给coord或coord\u value赋值,这会导致未定义的行为 我想做的就是在中为T使用tree\u项 template<typename T> struct tree_node { tree_node(T const& item) : item(item) { } tree_node(T&& item) : item(std::move(item)) { } bo
coord
或coord\u value
赋值,这会导致未定义的行为
我想做的就是在中为T
使用tree\u项
template<typename T>
struct tree_node
{
tree_node(T const& item)
: item(item)
{ }
tree_node(T&& item)
: item(std::move(item))
{ }
bool is_leaf() const noexcept {
return !left && !right;
}
T item;
std::shared_ptr<tree_node<T>> left, right;
};
模板
结构树节点
{
树节点(T常量和项目)
:项目(项目)
{ }
树节点(T&&item)
:项目(标准::移动(项目))
{ }
bool是_leaf()常量noexcept{
返回!左&!右;
}
T项;
std::共享_ptr左、右;
};
spliting\u line
和point
是我要存储在树中的两种类型的项。显然,我可以分别为分割线
和点
编写基类和派生类。但是,由于在这种情况下,我不想对这些项目执行任何类型的操作(我只想存储这些不同的类型),并且需要使用dynamic\u cast
或某种类型的标志,这将使我的代码过于复杂
那么,我该怎么办呢?您应该使用一个类来处理真正的变量类型所需的更多功能,而不是使用联合:
使用tree\u item=boost::variant<
分裂线,
std::valarray
};
variant
对象将确保根据存储的内容调用正确的析构函数。它还跟踪它所拥有的对象,以便您可以实际对其执行类型安全操作(这在您的联合上也是不可能的)。这就是虚拟继承的目的。使用公共基类型,可能称为tree\u item\u base
,包含两个派生类型,tree\u item\u point
和tree\u item\u spliting\u line
<代码>树节点
将需要使用引用或自动指针类型。您希望在设计中使用不受限制的联合,为了调用正确的析构函数,您必须存储有关联合内部和外部的信息,例如在树节点内部或某种其他包装类型,这将在某些枚举中保留数据类型,并调用正确的构造函数/析构函数
我已经在gcc/clang上尝试了您的代码,只做了一些轻微的修改,实际上它不会发出任何带有-pedantic的警告
#include <functional>
#include <iostream>
#include <valarray>
union tree_item
{
tree_item(std::valarray<double> const& ppoint) : point(ppoint) {
//new (&point)std::valarray<double>(ppoint);
}
tree_item(unsigned coord, double coord_value)
: splitting_line({ coord, coord_value })
{ }
~tree_item(){
// cannot call point dtor here because we dont know if it was used
}
struct {
unsigned coord;
double coord_value;
} splitting_line;
std::valarray<double> point;
};
int main() {
std::valarray<double> point={1,2,3};
// constructed with std::valarray, destructor must be called manually
tree_item nn(point);
std::cout << nn.point[2];
nn.point.~valarray<double>();
tree_item nn2(1.0, 2.0);
return 0;
}
#包括
#包括
#包括
联合树项目
{
树_项(std::valarray const&ppoint):点(ppoint){
//新(&point)标准::valarray(ppoint);
}
树项(无符号坐标、双坐标值)
:拆分_行({coord,coord_值})
{ }
~tree_item(){
//无法在此处调用点dtor,因为我们不知道是否使用了它
}
结构{
未签字合作社;
双坐标值;
}分裂线;
std::阵列点;
};
int main(){
std::valarray point={1,2,3};
//使用std::valarray构造,必须手动调用析构函数
树_项nn(点);
STD::如果没有共同的操作,那么把这两种类型的东西存储在同一数据结构中是否有意义?我觉得人们不会经常问自己这个问题……布瑞恩实际上,他们在同一棵树上是很重要的。我永远不会把联盟用作C++类。不幸的是,我不能在这个过程中使用Boost。project.@0xbadf00d您仍然可以复制他们的操作方式(或找到类似的博客)
using tree_item = boost::variant<
splitting_line,
std::valarray<double>
};
#include <functional>
#include <iostream>
#include <valarray>
union tree_item
{
tree_item(std::valarray<double> const& ppoint) : point(ppoint) {
//new (&point)std::valarray<double>(ppoint);
}
tree_item(unsigned coord, double coord_value)
: splitting_line({ coord, coord_value })
{ }
~tree_item(){
// cannot call point dtor here because we dont know if it was used
}
struct {
unsigned coord;
double coord_value;
} splitting_line;
std::valarray<double> point;
};
int main() {
std::valarray<double> point={1,2,3};
// constructed with std::valarray, destructor must be called manually
tree_item nn(point);
std::cout << nn.point[2];
nn.point.~valarray<double>();
tree_item nn2(1.0, 2.0);
return 0;
}