2013-12-10 65 views
3
#include <iostream> 

int main() { 
    int a[] = { 21, 213, 45 }; 
    static_assert(a[22], "error for a\n"); 
    return (0); 
} 

我有形狀象int陣列的查找表,我需要在編譯時是否使用了[]操作的可能可能導致讀取超出範圍。當[]運算符失敗時會發生什麼,我需要一個斷言?

我知道一個static_assert需求基本上由兩個部分:

  • 常量表達式
  • 給定的表達式應該返回一個boolg++ 4.8.1可轉換/相當於bool

現在一個initializer_list應該是C++ 11中的一個常量表達式,並且我不知道有多少次我看到了像這樣編寫的if構造是if(arr[N]){...};所以這個斷言有什麼問題?

+0

的靜態斷言必須是在編譯時解析的參數。 'a'是一個'ints'的數組,'a [22]'返回一個'int',直到運行時纔會知道它的值。它超出界限的事實不會阻止你檢查它。 基本上,無論數組訪問是否超出限制,幾乎總是隻能在**運行時才知道,所以這在一個不適合static_assert的地方。 –

回答

4

我想你可以用一個小模板來推廣你想要的東西。

template<typename T,int N> constexpr bool bounds_check(T (&array)[N], int i) 
{ 
    return i < N; 
} 

看到它在行動:http://ideone.com/kj51N0

2

訪問數組邊界是未定義的行爲。所以,事實上任何事情都可能發生。

靜態斷言全部是關於編譯時間失敗。這將不會被捕獲,直到運行時間:太遲。

+0

所以有一個initializer_list屬性是一個常量表達式在這裏沒用嗎?在我看來,這是浪費編譯時的信息,我很難相信我需要等待運行時檢查 – user2485710

2

a[22]不是一個常量表達式。另外,它沒有範圍檢查,因爲編譯器將原生數組的訪問重寫爲*(a + 22)。要獲得範圍檢查,您需要將a設置爲std::array,並且C++庫需要啓用範圍檢查,其中一些操作只能在調試模式下執行。

什麼會在這裏,我覺得工作是,如果你沒有static_assert(sizeof(a)/sizeof(*a) > 22, "a not large enough")

+0

信任的+1,但'static_assert'工作嗎? – Bathsheba

+0

所以initializer_list對於assert是沒用的? – user2485710

+0

@Bathsheba:我沒有嘗試過。 –

1

我認爲你可以使用:

int a[] = { 21, 213, 45 }; 
static_assert(sizeof(a)/sizeof(a[0]) > 22, "error for a\n"); 
return (0); 

但是,這是一個非常奇怪的檢查做。只有在編譯時已知索引(22)和大小a纔有效。

1
template<std::size_t Index, typename T, std::size_t N> 
T& at(T(&a)[N]) { 
    static_assert(Index < N, "Out of bounds"); 
    return a[Index]; 
} 
template<std::size_t Index, typename T, std::size_t N> 
T& at(std::array<T,N>& a) { 
    static_assert(Index < N, "Out of bounds"); 
    return a[Index]; 
} 
template<std::size_t Index, typename T, std::size_t N> 
T const& at(std::array<T,N> const& a) { 
    static_assert(Index < N, "Out of bounds"); 
    return a[Index]; 
} 

使用:

int main() { 
    int a[] = { 21, 213, 45 }; 
    int x = at<22>(a); // fails to compile 
    return (0); 
} 
相關問題