问题
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