是的,原則上這應該是可能的。這是一個有點讓你開始:
template <class T, std::size_t... Dim>
using VariableLengthTable = std::tuple<std::array<T, Dim>...>;
這是std::array
,每個具有由模板參數之一指定的長度的元組。
注意,由於一個std::array
的長度是它的類型的一部分,第一尺寸不能是一個數組,因爲它的成員需要不同的類型。但是,std::tuple
很好地工作。只要你願意使用std::get<i>
而不是[i]
,並且將自己限制在編譯時間i
s,那麼你應該很好。
如果編譯時i
是不夠的,你有兩個選擇:
一個,使用VariableLengthTable
如上並添加運行到編譯時轉換。從概念上講,這樣的事情switch
:
T& get(std::size_t x, std::size_t y)
{
switch (x) {
case 0: return std::get<0>(varLenTable)[y];
case 1: return std::get<1>(varLenTable)[y];
case 2: return std::get<2>(varLenTable)[y];
// and so on
}
}
在現實中,你可能需要編寫這個使用遞歸或繼承,以避免編譯時出界外的訪問。 Boost.Preprocessor可能有幫助。
兩個,將所有數據存儲在一個順序緩衝區中並在運行時將其索引到它。類似這樣的:
template <class T, std::size_t... Dim>
class VariableLengthTable
{
static const std::array<std::size_t, sizeof...(Dim)> dims = {{ Dim... }};
static const std::array<std::size_t, sizeof...(Dim)> cumulDims = [](){
std::array<std::size_t, sizeof...(Dim)> result;
result[0] = 0;
for (std::size_t idx = 1; idx < sizeof...(Dim); ++idx) {
result[idx] = result[idx - 1] + dims[idx];
}
return result;
}();
std::array<T, cumulDims[sizeof...(Dim) - 1] + dims[sizeof...(Dim) - 1]> data;
public:
T& get(std::size_t x, std::size_t y)
{
return data[cumulDims[x] + y];
}
};
上面的代碼是顯示原理,不保證按原樣編譯。
我不太確定你需要一個可變模板來做到這一點。不是'std :: vector>'或者至少是'std :: array ,N>'一個選項? –
我正在尋找零成本或非常非常低的成本。 'std :: vector'對於我們的應用程序來說太大了。 –