当[]运算符失败并且我需要断言时会发生什么?

时间:2013-12-10 16:06:18

标签: c++ c++11 assert static-assert

#include <iostream> 

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

我有一个形状类似于int数组的查找表,我需要在编译时检查是否使用[]运算符可能导致读取超出范围。

我知道static_assert基本上需要两件事:

  • 常量表达
  • 给定的表达式应返回bool或可转换/等效于bool

现在在g++ 4.8.1中,initializer_list应该是C ++ 11中的常量表达式,我不知道有多少次我看到if构造像这样编写{ {1}};那断言怎么了?

5 个答案:

答案 0 :(得分:4)

我认为你可以用一点模板魔法来概括你想要的东西。

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

查看实际操作:http://ideone.com/kj51N0

答案 1 :(得分:2)

访问数组边界是未定义的行为。所以,任何事情都可能发生。

静态断言都是关于编译时失败的。在运行时间之前不会捕获:太晚了。

答案 2 :(得分:2)

a[22]不是常量表达式。此外,它没有范围检查,因为编译器会将对本机数组的访问重写为*(a + 22)。要获得范围检查,您需要将a构建为std::array,而C ++库需要启用范围检查,有些只能在调试模式下进行。

如果你做static_assert(sizeof(a)/sizeof(*a) > 22, "a not large enough")

,我认为这里有什么用

答案 3 :(得分:1)

我认为你可以使用:

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

但这是一个非常奇怪的检查。它仅在编译时知道索引(22)和a的大小时才有效。

答案 4 :(得分: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);
}