2013-05-12 32 views
3

我有一個模板類有以下規格:如何提取可變參數模板參數列表爲n維數組

template <typename T, size_t... Dims> class Array; 

說出來可以如下使用:

// Define a 2X3X4 array of integers. Elements are uninitialized. 
Array<int, 2, 3, 4> a, b; 
Array<short, 2, 3, 4> c; 
Array<int, 0> e1; // This line must cause a compile-time error. 

我怎樣才能實現這個功能?我想如果我可以提取所有的參數列表,我可以創建n維數組作爲直接遞歸調用。我該怎麼辦呢,現在

回答

4

您可以創建一個編譯時特質,你想要做什麼:

#include <type_traits> 

template <std::size_t... Ts> 
struct not_zero {}; 

template <std::size_t N> 
struct not_zero<N> : std::integral_constant<bool, N> {}; 

template <std::size_t N, std::size_t... Ts> 
struct not_zero<N, Ts...> : std::integral_constant<bool, N && not_zero<Ts...>::value> {}; 

template <typename T, std::size_t... Ts> 
struct Array 
{ 
    static_assert(not_zero<Ts...>::value, "Dimension cannot be 0"); 
}; 

template struct Array<int, 3>; // OK 
template struct Array<int, 3, 2, 1, 0>; // error: static assertion failed: Dimension cannot be 0 

看到一個演示here

2

像這樣的事情也許

namespace mine { 

    template<typename T, size_t first, size_t... rest> 
    struct multi_array__ { 
     enum { dims = sizeof...(rest) }; 
     static_assert(first,"dimension can not be zero!"); 
     typedef std::array< typename multi_array__<T, rest...>::type, first > type; 
    }; 


    template<typename T, size_t first> 
    struct multi_array__<T,first> { 
     enum { dims = 1 }; 
     static_assert(first,"dimension can not be zero!"); 
     typedef std::array<T,first> type; 
    }; 

    template <typename T, std::size_t... ds> 
    using multi_array = typename multi_array__<T, ds ...>::type; 

}; 

您可以使用它像這樣

mine::multi_array <int,2,3,4> arr1 = {}; 
// multi_array<int,2,3,0,4> arr3; // This fails 
mine::multi_array <int,3,4> arr2 = {}; 

分配這樣的工作太

arr2[0] = arr1[0][0]; 

Here是一個簡單的測試程序。

+0

使用'template 使用Array = typename multi_array :: type;'擴大此答案,然後您不需要使用':: type'。 – 2013-05-12 18:31:53

+0

@sftrabbit當然可以。 – stardust 2013-05-12 18:33:02

+0

@sftrabbit這實際上是一個非常好的技巧。謝謝你。沒有想到它。 – stardust 2013-05-12 18:34:42

2

爲它創建一個專業化:

#include <iostream> 

template <typename T, std::size_t... Dims> 
struct Array {}; 

template <typename T> 
struct Array<T, 0>; // leave as an incomplete type 

int main() 
{ 
    Array<int, 3> x; // OK 
    Array<int, 0> y; // error: aggregate ‘Array<int, 0u> y’ has incomplete type and cannot be defined 
}