2012-06-09 27 views
0

我想編寫一個n維直方圖類。它應該在倉包含其它倉等等,其中每個倉包含最小和最大範圍內的形式,並且一個指針到下一個維度倉定義一個深度/尺寸未知的C++模板

的倉被定義像

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>>> 

這可能嗎?

Regards

+0

你是如何指定維數的?你的僞代碼在這裏是不存在的...... – ildjarn

+0

@ildjarn:_run time_他說 –

+0

@ K-ballo:這只是它的一部分;它傳遞給構造函數還是在構造之後提供? – ildjarn

回答

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; 
}; 

只能在運行時指定的尺寸在一定程度上。如果它被固定值綁定,則可以動態選擇適當的類型。但是,考慮使用一維矢量而不是多維鋸齒矢量!

+0

工作正常。非常感謝輝煌的解決方案 –

+0

@MoatazElmasry:不客氣:) – bitmask

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計算出節點是否實際上是另一個向量或對象。從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繼承,並且表示對象本身。

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的載體中。

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維,但我邀請您來嘗試自己做。

+0

非常感謝,這個解決方案也應該工作。我喜歡「位掩碼」的解決方案。它更簡單。問候 –