首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >定义深度/尺寸未知的c++模板

定义深度/尺寸未知的c++模板
EN

Stack Overflow用户
提问于 2012-06-10 02:32:58
回答 2查看 181关注 0票数 0

我想写一个n维直方图类。它的形式应该是包含其他仓位的仓位等,其中每个仓位包含最小和最大范围,以及指向下一维仓位的指针

bin的定义如下

代码语言:javascript
运行
复制
template<typename T>
class Bin {
 float minRange, maxRange;
 vector<Bin<either Bin or ObjectType>> bins;
}

这个定义是递归的。因此,在运行时,用户定义直方图的维度

代码语言:javascript
运行
复制
so if its just 1-dimension, then
Bin<Obj>
while 3-dimensions
Bin<Bin<Bin<Obj>>>

这个是可能的吗?

问候

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-06-10 02:39:23

当然,C++11为模板提供了可变长度的参数列表。即使没有C++11,如果所有维度都具有相同的类型,您也可以使用特殊化:

代码语言:javascript
运行
复制
template <typename T, unsigned nest>
struct Bin {
  std::vector<Bin<T, (nest-1)> > bins;
};

template <typename T>
struct Bin<T,0> {
  T content;
};

您只能在运行时指定一定程度的维度。如果它是由固定值绑定的,您甚至可以动态地选择适当的类型。但是,考虑使用一维向量而不是多维锯齿向量!

票数 5
EN

Stack Overflow用户

发布于 2012-06-10 03:30:04

要获得您建议的确切语法,请执行以下操作:

代码语言:javascript
运行
复制
template <typename T>
class Bin
{
    float minRange, maxRange;
    std::vector<T> bins;
};

并且它应该完全按照您在问题中提出的内容进行操作:

代码语言:javascript
运行
复制
Bin< Bin< Bin<Obj> > > bins;

为了动态地(在运行时)做到这一点,我采用了一些多态性。这个例子有点复杂。首先,有一个基类型。

代码语言:javascript
运行
复制
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确定节点实际上是另一个向量,还是对象。

代码语言:javascript
运行
复制
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,并表示对象本身。

代码语言:javascript
运行
复制
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);
};

BinBinNode的向量。

代码语言:javascript
运行
复制
template <typename T>
inline const T & BinNode<T>::operator = (const T &t) {
    if (!is_object()) throw 0;
    return *is_object() = t;
}

如果BinNode实际上是object,则允许赋值给它;

代码语言:javascript
运行
复制
template <typename T>
BinNode<T> & BinNode<T>::operator[] (unsigned i) {
    if (!is_vector()) throw 0;
    return (*is_vector())[i];
}

如果BinNode是向量,则允许对其进行索引。

代码语言:javascript
运行
复制
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];
}

如果存在索引项,则返回索引项,否则根据当前维深度创建相应的项。为漂亮的打印添加重定向操作符:

代码语言:javascript
运行
复制
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

代码语言:javascript
运行
复制
int dim = 3;
Bin<float> v(dim);
v[0][1][2] = 3.14;
std::cout << v[0][1][2] << std::endl;

它目前不支持0维,但我邀请您尝试自己来做。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10963552

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档