Automatically check bounds in std::vector [duplicate]

僤鯓⒐⒋嵵緔 提交于 2019-12-01 15:08:35

问题


During active development of a class that uses std::vector, it often happens that an index is out of bounds. (See this code review question for a practical example.) When using operator[], this results in undefined behavior. Still, the [] syntax is easy to read an more convenient than writing .at().

Therefore I'd like to write my code using the [] operator, but at the same time have bounds checks enabled. After testing the code, it should be very easy to remove the bounds checks.

I'm thinking of the following code:

util::bound_checked<std::vector<int>> numbers;

numbers.push_back(1);
numbers.push_back(2);
numbers.push_back(3);
numbers.push_back(4);
std::cout << numbers[17] << "\n";

To me, this utility template seems to be so straight-forward that I'd expect it to exist. Does it? If so, under which name?


回答1:


To me, this utility template seems to be so straight-forward that I'd expect it to exist

For gcc it does exist. gcc libstdc++ has a set of debug containers. For std::vector it has __gnu_debug::vector debug container. See documentation.




回答2:


I don't think anything like this exists, but it's fairly easy to create:

template <class Container>
struct bound_checked : public Container
{
  using Container::Container;

  auto operator[] (typename Container::size_type i) -> decltype(this->at(i))
  { return this->at(i); }

  auto operator[] (typename Container::size_type i) const -> decltype(this->at(i))
  { return this->at(i); }
};

[Live example]

Note that the above actually uses a discouraged practice, namely public inheritance from standard containers (which are not designed for it). My understanding of your question was that this wrapper would be used in testing purposes only, which is fine. However, if you want this to remain in production and want to be on the very safe side, use non-public inheritance:

template <class Container>
struct bound_checked : private Container
{
  using Container::Container;

  auto operator[] (typename Container::size_type i) -> decltype(this->at(i))
  { return this->at(i); }

  auto operator[] (typename Container::size_type i) const -> decltype(this->at(i))
  { return this->at(i); }

  using Container::begin;
  using Container::end;
  using Container::at;
  using Container::insert;
  // ... you get the idea
};



回答3:


If you use GCC (or MinGW) with libstdc++, #define _GLIBCXX_DEBUG will do what you want.

Or even better, define it with a flag: -D_GLIBCXX_DEBUG.




回答4:


Does it? If so, under which name?

I'm pretty sure it does exist. Many compilers enable std::vector<T>::at() as implementation for std::vector::operator[]() if a compiler intrinsic __DEBUG building macro is enabled.

Therefore I'd like to write my code using the [] operator, but at the same time have bounds checks enabled. After testing the code, it should be very easy to remove the bounds checks.

Regarding the naming, I'd say that's debug vs. release building. The checks will be removed when the code is compiled without the __DEBUG definition.



来源:https://stackoverflow.com/questions/48035379/automatically-check-bounds-in-stdvector

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!