我正在开发一个项目,我需要能够拥有特定类型的数据结构。本质上,我需要能够有一个向量,它可以存储整数或其他向量。然后同样的想法需要应用于第二个向量。我知道有一个容器包含自己,但我想知道是否有某种方法可以做到这一点。
也许一个例子会澄清。我希望能够拥有这样的集合:
[[1,2], [[3,4], 5], [6, 7]]
我认为我可以在“系列”和“平行”无限期地进行整理和向量。我知道这是一个棘手的问题,但是有什么方法可以做到这一点。我的一个想法是我们可以有一个向量,其中Elem是我们定义的一个类,它包含一个表示它的嵌套深度的int,以及一个指向堆分配元素的void *指针。
我觉得这里可以做一些多态魔术,但不太确定。
答案 0 :(得分:3)
某些boost魔法怎么样?
#include <vector>
#include <boost/variant.hpp>
#include <boost/variant/recursive_wrapper.hpp>
// A recursive tree structure made of std::vector.
template< typename T, class Allocator = std::allocator<T> >
struct vector_tree :
std::vector<
boost::variant< T, boost::recursive_wrapper< vector_tree< T, Allocator > > >,
Allocator >
{
using base = std::vector<
boost::variant< T, boost::recursive_wrapper< vector_tree< T, Allocator > > >,
Allocator >;
// Forward all constructors of the base class.
using base::base;
};
此类型允许无限制嵌套,并具有非常干净的初始化语法。
using mytree = vector_tree<int>;
// Construct a nested vector_tree with initializer list.
mytree tree{
1,
2,
mytree{
mytree{ 3, 4, 5 },
6,
}
};
// Add more stuff.
tree.push_back( 42 );
tree.push_back( mytree{ 43, 44 } );
// Add something to a child vector_tree.
// NOTE: boost::get() will throw a boost::bad_get exception if requested type is invalid
boost::get<mytree>( tree[ 2 ] ).push_back( 99 );
// To avoid the boost::bad_get exception, we can check if the child actually is a vector_tree:
if( mytree* pchild = boost::get<mytree>( &tree[ 2 ] ) )
{
(*pchild)[ 1 ] = 88;
}
boost::recursive_wrapper
是必需的,因为boost::variant
通常需要完整的类型,但在声明时vector_tree
仍然不完整。
boost::recursive_wrapper
实际上并不神奇。它只是一个指针的包装器!我们知道,可以为不完整类型声明指针而不会出现问题。这个包装类只是隐藏了一个事实,即通过处理分配,释放和提供值语义来使用指针。它具有boost::variant
的特殊支持,使得包装器完全透明,因此可以使用变体,就好像根本没有包装类一样。
注意:由于C ++ 17有std::variant
但是AFAIK没有boost::recursive_wrapper
等效的,可以透明地处理嵌套。
答案 1 :(得分:1)
如果要使用多态,可以定义基struct
,并从中派生出包含std::vector<*base>
的结构,并派生另一个包含int
的结构。你的main函数将包含第一个派生类的实例,它可以包含指向自身的指针,或者包含第二个派生类。这将允许包含int的向量内的向量。
要存储深度等信息,您可以在基础结构中使用int depth
,其中构造函数将传递当前深度并添加一个。
答案 2 :(得分:1)
以下是您正在寻找的内容:
template <typename T>
class NestableVector {
private:
struct element {
virtual element* copy() const = 0;
};
struct vector_element : public element {
NestableVector value;
element* copy() const;
};
struct normal_element : public element {
T value;
element* copy() const;
};
class copy_ptr { // specialized smart pointer that copies underlying object when copied
private:
element* ptr;
public:
copy_ptr(element*);
copy_ptr(const copy_ptr&); // copies *ptr into new object
void operator=(const copy_ptr&); // same as above
};
std::vector<copy_ptr> v; // underlying vector
public:
// interface to v here
};
您定义了一个特殊的element
类型,它有两个子类vector_element
和normal_element
。这两个函数都重载了基类的copy()
函数,该函数在新的智能指针类copy_ptr
中使用,它复制了它自己在复制时指向的元素。我们使用智能指针,以便在v
中复制东西时,复制元素本身,而不是指向它们的指针。