我想写一个n维直方图类。它应该是包含其他箱子的箱子的形式,其中每个箱子包含最小和最大范围,以及指向下一个维度箱子的指针
bin定义为
template<typename T>
class Bin {
float minRange, maxRange;
vector<Bin<either Bin or ObjectType>> bins;
}
这个定义是递归的。因此,在运行时,用户定义直方图的维度
so if its just 1-dimension, then
Bin<Obj>
while 3-dimensions
Bin<Bin<Bin<Obj>>>
这可能吗?
此致
答案 0 :(得分:5)
当然,C ++ 11具有模板的可变长度参数列表。即使没有C ++ 11,如果您的所有维度都具有相同的类型,也可以使用专业化:
template <typename T, unsigned nest>
struct Bin {
std::vector<Bin<T, (nest-1)> > bins;
};
template <typename T>
struct Bin<T,0> {
T content;
};
您只能在运行时指定一定程度的维度。如果它受固定值限制,您甚至可以动态选择适当的类型。但是,请考虑使用一维向量而不是多维锯齿状向量!
答案 1 :(得分:1)
要获得您建议的确切语法,请执行以下操作:
template <typename T>
class Bin
{
float minRange, maxRange;
std::vector<T> bins;
};
它应该完全按照你提出的问题行事:
Bin< Bin< Bin<Obj> > > bins;
为了动态地(在运行时),我采用了一些多态性。这个例子有点复杂。首先,有一个基本类型。
template <typename T>
class BinNode {
public:
virtual ~BinNode () {}
typedef std::shared_ptr< BinNode<T> > Ptr;
virtual T * is_object () { return 0; }
virtual const T * is_object () const { return 0; }
virtual Bin<T> * is_vector() { return 0; }
const T & operator = (const T &t);
BinNode<T> & operator[] (unsigned i);
};
BinNode
计算出节点实际上是另一个向量还是对象。
template <typename T>
class BinObj : public BinNode<T> {
T obj;
public:
T * is_object () { return &obj; }
const T * is_object () const { return &obj; }
};
BinObj
继承自BinNode
,代表对象本身。
template <typename T>
class Bin : public BinNode<T> {
typedef typename BinNode<T>::Ptr Ptr;
typedef std::map<unsigned, std::shared_ptr<BinNode<T> > > Vec;
const unsigned dimension;
Vec vec;
public:
Bin (unsigned d) : dimension(d) {}
Bin<T> * is_vector() { return this; }
BinNode<T> & operator[] (unsigned i);
};
Bin
是BinNode
的矢量。
template <typename T>
inline const T & BinNode<T>::operator = (const T &t) {
if (!is_object()) throw 0;
return *is_object() = t;
}
如果它实际上是对象,则允许分配给BinNode
;
template <typename T>
BinNode<T> & BinNode<T>::operator[] (unsigned i) {
if (!is_vector()) throw 0;
return (*is_vector())[i];
}
如果BinNode
是矢量,则允许将其编入索引。
template <typename T>
inline BinNode<T> & Bin<T>::operator[] (unsigned i)
{
if (vec.find(i) != vec.end()) return *vec[i];
if (dimension > 1) vec[i] = Ptr(new Bin<T>(dimension-1));
else vec[i] = Ptr(new BinObj<T>);
return *vec[i];
}
返回索引项(如果存在),否则根据当前维度深度创建相应的条目。添加重定向运算符以进行漂亮的打印:
template <typename T>
std::ostream &
operator << (std::ostream &os, const BinNode<T> &n) {
if (n.is_object()) return os << *(n.is_object());
return os << "node:" << &n;
}
然后您可以像这样使用Bin
:
int dim = 3;
Bin<float> v(dim);
v[0][1][2] = 3.14;
std::cout << v[0][1][2] << std::endl;
它目前不支持0维度,但我邀请您尝试自己动手。