2014-03-28 31 views
3

我有一個模板化函數,我想static_assert它的類型大小爲3。此代碼說明了什麼,我試圖做的,但不工作:在std :: array上使用std :: extent

template < typename T > 
void foo(T& param) 
{ 
    // This line is the one that I need to figure out how to write 
    static_assert(3 == std::extent<T>::value, "param must have a size of 3"); 
} 

int main(void) 
{ 
    int cArray[3]; 
    std::array< int, 3 > stdArray; 

    foo(cArray); 
    foo(stdArray); 
} 
+1

嘗試通過參考?我不認爲C數組喜歡按照這樣的價值傳遞。 –

+0

你應該解釋它如何「不起作用」。你有錯誤嗎?哪個? – sth

+1

我認爲他/她在編譯時得到「參數必須是3的大小」。 – DrD

回答

2

這建立在iavr的解決方案。

template < typename T > 
void foo(T& param) 
{ 
    static_assert(3 == (std::is_array<T>::value ? std::extent<T>::value : std::tuple_size<T>::value), "param must have a size of 3"); 
} 
+0

糾正我自己的錯誤後,它似乎工作!非常優雅的解決方案,恭喜! – DrD

+1

不錯。還有另一種方法是使用array_size = std :: integral_constant :: value?來定義'template 。 std :: extent < T > :: value:std :: tuple_size < T > :: value>;'。 – iavr

+0

@iavr我在你的回答中也看到了'using'關鍵字。你能向我解釋那是做什麼的嗎? –

0

我懷疑你,因爲在編譯時有這個錯誤(這是當* static_assert *評估)的尺寸CARRAYstdArray是未知的,的std ::程度返回零:

http://en.cppreference.com/w/cpp/types/extent

事實上,如果你改變的條件到z等於錯誤消失ERO

static_assert(std::extent<T>::value == 0, "param is not zero"); 

然而,因爲它已經在其他職位指出,的std ::程度不會爲的std ::陣列,只爲內建數組如CARRAY工作

後OP的編輯: 現在你已經修改接受一個參考,你就會有的std ::程度報告3 CARRAY和0(零)爲stdArray。因此,在編譯時您將繼續發生異常,因爲stdArray的維數不是3.

8

std::extent是爲內置陣列定義的。代替std::array使用std::tuple_size。我不知道某些特質上都有效,但它很容易寫一個:

template<typename T> 
struct array_size : std::extent<T> { }; 

template<typename T, size_t N> 
struct array_size<std::array<T,N> > : std::tuple_size<std::array<T,N> > { }; 

,這裏是你的foo,糾正/廣義(live example):

template < typename T > 
void foo(T&& param) 
{ 
    using U = typename std::remove_cv<typename std::remove_reference<T>::type>::type; 
    static_assert(3 == array_size<U>::value, "param must have a size of 3"); 
} 

喜歡一個普遍的參考T&& param ,否則只能使用左值。

+1

這是真的,但即便如此,他仍然會對cArray產生相同的錯誤,這是一個內置陣列 – DrD

+0

@DDD爲什麼?它的大小在編譯時已知,對嗎? – iavr

+0

@DrD:沒有對'T&param'進行修正。 – aschepler

1

我想不出一種方法來編寫一個處理兩個函數的函數,但這是重載的目的。

template <std::size_t N, typename T, std::size_t Bound> 
void check_array_size(T (&)[Bound]) 
{ 
    static_assert(Bound == N, "incorrect array size"); 
} 

template <std::size_t N, typename T, std::size_t Bound> 
void check_array_size(const std::array<T,Bound>&) 
{ 
    static_assert(Bound == N, "incorrect array size"); 
} 

template <std::size_t N> 
void check_array_size(...) 
{ 
    static_assert(N<0, "argument is not an array"); 
} 

template <typename T> 
void foo(T& param) 
{ 
    check_array_size<3>(param); 
    // actual function implementation... 
}