I'm looking to implement a function that determines whether a given pointer points into a given buffer. The specification:
template <typename T>
bool points_into_buffer (T *p, T *buf, std::size_t len);
If there is some n
, 0 <= n && n < len
, for which p == buf + n
, returns true
.
Otherwise, if there is some n
, 0 <= n && n < len * sizeof(T)
, for which reinterpret_cast<char *>(p) == reinterpret_cast<char *>(buf) + n
, the behaviour is undefined.
Otherwise, returns false
.
The obvious implementation would look something like
template <typename T>
bool points_into_buffer (T *p, T *buf, std::size_t len) {
return p >= buf && p < buf + len;
}
but that has undefined behaviour in standard C++: relational comparisons of pointers are only defined for pointers into the same array.
An alternative would be to use the standard library's comparer objects:
template <typename T>
bool points_into_buffer (T *p, T *buf, std::size_t len) {
return std::greater_equal<T *>()(p, buf) && std::less<T *>()(p, buf + len);
}
which is guaranteed to return true
when I want it to return true
, and avoids undefined behaviour, but allows for false positives: given int a; int b;
, it allows a result of true
for points_into_buffer(&a, &b, 1)
.
It can be implemented as a loop:
template <typename T>
bool points_into_buffer (T *p, T *buf, std::size_t len) {
for (std::size_t i = 0; i != len; i++)
if (p == buf + i)
return true;
return false;
}
However, compilers have trouble optimising away that loop.
Is there a valid way of writing this, where with current compilers and optimisations enabled, the result is determined in constant time?
See Question&Answers more detail:
os