What happens when the [] operator fails and I need an assert on that?

269 views Asked by At
#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 ?

5

There are 5 answers

0
Mark Ransom On BEST ANSWER

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

0
Yakk - Adam Nevraumont On
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);
}
1
Bathsheba On

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.

5
Zan Lynx On

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")

0
ikegami On

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.