2012-08-12 58 views
1

我正在尋找一種方法來選擇性地包含C++類的成員來生成POD結構。我發現這工作得相當好,但它們是非標準:帶有可選成員的POD模板類

#include <iostream> 

template <int v, int n, int t> 
struct Point 
{ 
    int vertex[v]; 
    float normal[n]; 
    double texcoord[t]; 
}; 

int main() 
{ 
    std::cout << (sizeof (Point<0,0,1>)) << std::endl; 
    std::cout << (sizeof (Point<1,0,1>)) << std::endl; 
    std::cout << (sizeof (Point<1,1,2>)) << std::endl; 
    std::cout << (sizeof (Point<0,0,0>)) << std::endl; 
    return 0; 
} 

有那麼點< 1,0,0>將只包含一個頂點(int類型實際上是在實踐中的Vector3類型),等等。主要原因是爲OpenGL輕鬆支持交錯數組。

+1

是什麼讓你認爲這有效?你使用什麼編譯器?在'gcc'中,有一個擴展,你可以寫'int x [0]',這並不意味着'x'不存在。作爲參考:http://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html – 2012-08-12 20:23:51

+0

嗯,它意味着,它不需要空間,它會指向前一個成員之後的地方,對嗎?我還沒有真正把這個工作,但它似乎工作上面的測試。不過,我認爲這是一個解決問題的好方法。 – solinent 2012-08-12 20:27:51

回答

4

也許嘗試這樣的事:

#include <type_traits> 

template <unsigned int v, unsigned int n, unsigned int t> 
struct Point 
{ 
    int data[v + n + t]; 

    template <unsigned int i> 
    typename std::enable_if<(i < v), int &>::type 
    vertex() { return data[i]; } 

    template <unsigned int i> 
    typename std::enable_if<(i < v + n), int &>::type 
    normal() { return data[v + i]; } 

    template <unsigned int i> 
    typename std::enable_if<(i < v + n + t), int &>::type 
    texcoord() { return data[v + n + i]; } 
}; 

用法:

Point<1,1,2> p; 
p.vertex<0>() = 50; 
+0

不幸的是,他們不會都是整數。其中一個可能是vector3,一個可能是vector2等等,我會澄清這個問題。不過,這看起來很有希望。 – solinent 2012-08-12 20:35:30

+0

@solinent:作爲底層結構的一系列工會呢? – 2012-08-12 20:42:25

+0

@KerrekSB:對'vertex()'輕微的打字錯誤,你想'返回數據[i]'。 – jxh 2012-08-12 21:11:15

0

你可以這樣做,但你需要專業化。

編輯:符合每個陣列不同類型的新問題要求。儘管模板參數沒有簽名。

template <> struct Point<0, 0, 0> {}; 
template <unsigned v> struct Point<v, 0, 0> { int vertex[v]; }; 
template <unsigned n> struct Point<0, n, 0> { float normal[n]; }; 
template <unsigned t> struct Point<0, 0, t> { double texcoord[t]; }; 
template <unsigned v, unsigned n> struct Point<v, n, 0> { 
    int vertex[v]; 
    float normal[n]; 
}; 
template <unsigned v, unsigned t> struct Point<v, 0, t> { 
    int vertex[v]; 
    double texcoord[t]; 
}; 
template <unsigned n, unsigned t> struct Point<0, n, t> { 
    float normal[n]; 
    double texcoord[t]; 
}; 

每個專業化省去了相關聯的陣列時,其相應的模板參數具有值0。對於如圖所示的三個項目,專業化枚舉不會太大,並且提供與原始帖子訪問元素完全相同的語法,但使用標準的C++構造。

將此技術擴展到3個陣列之外將會非常麻煩。但是,可以使用腳本來管理它,以便爲您生成專門化。

2

std::array<T, 0>是有效的,不像T[0]真的是一個更好的解決方案。不幸的是,由於這隻適用於C++ 11,我無法弄清楚它的Boost同名boost::array是否也有這樣的支持。

也可以自己編寫一個array的幫手。

+0

+1,因爲這是一個非常好的建議,但它不會是OP所要求的POD。 – jxh 2012-08-12 21:32:13

+0

但'array '可能會導致不必要的膨脹,不是嗎? – 2012-08-12 21:35:40

+0

@ user315052我懷疑憑藉'std :: array '是一個聚集,它是一個POD iff'T'(我沒有時間仔細檢查)。 – 2012-08-12 21:43:13