문제

#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:

  • a constant expression
  • the given expression should return a 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);
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top