Pregunta

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

¿Fue útil?

Solución

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

Otros consejos

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);
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top