I think you can generalize what you want with a little template magic.
template<typename T,int N> constexpr bool bounds_check(T (&array)[N], int i)
{
return i < N;
}
See it in action: http://ideone.com/kj51N0
문제
#include <iostream>
int main() {
int a[] = { 21, 213, 45 };
static_assert(a[22], "error for a\n");
return (0);
}
I have a lookup table shaped like an array of int
, I need to check at compile time if the use of the []
operator could possibly lead to a read that is out of the scope.
I know that a static_assert
needs basically 2 things:
bool
or be convertible/equivalent to a bool
Now in g++ 4.8.1
an initializer_list
should be a constant expression in C++11, and I don't know how many times I have seen an if
construct written like this if(arr[N]){...}
; so what is wrong with this assert ?
해결책
I think you can generalize what you want with a little template magic.
template<typename T,int N> constexpr bool bounds_check(T (&array)[N], int i)
{
return i < N;
}
See it in action: http://ideone.com/kj51N0
다른 팁
Accessing out of the array bounds is undefined behaviour. So, literally anything could happen.
Static assertions are all about compile time failures. This will not be captured until run time: too late.
a[22]
isn't a constant expression. Plus, it has no range check because access to native arrays is rewritten to *(a + 22)
by the compiler. To get a range check you'd need to build a
as a std::array
plus the C++ library would need to have a range check enabled, which some do but only in debug mode.
What would work here I think is if you did static_assert(sizeof(a)/sizeof(*a) > 22, "a not large enough")
I think you can use:
int a[] = { 21, 213, 45 };
static_assert(sizeof(a)/sizeof(a[0]) > 22, "error for a\n");
return (0);
But that's a very weird check to do. It only works if the index (22
) and the size of a
being known at compile time.
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];
}
use:
int main() {
int a[] = { 21, 213, 45 };
int x = at<22>(a); // fails to compile
return (0);
}