Я ищу реализацию функции, которая определяет, указывает ли данный указатель на данный буфер. Спецификация:
template <typename T>
bool points_into_buffer (T *p, T *buf, std::size_t len);
Если есть n
, 0 <= n && n < len
, для которого p == buf + n
, возвращает true
.
В противном случае, если есть n
, 0 <= n && n < len * sizeof(T)
, для которого reinterpret_cast<char *>(p) == reinterpret_cast<char *>(buf) + n
, поведение undefined.
В противном случае возвращает false
.
Очевидная реализация будет выглядеть примерно так:
template <typename T>
bool points_into_buffer (T *p, T *buf, std::size_t len) {
return p >= buf && p < buf + len;
}
но имеет поведение undefined в стандартном С++: реляционные сравнения указателей определяются только для указателей в один и тот же массив.
Альтернативой может быть использование стандартных объектов сравнения библиотек:
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);
}
которому гарантируется возвращение true
, когда я хочу, чтобы он возвращал true
, и избегает поведения undefined, но допускает ложные срабатывания: данный int a; int b;
, он позволяет получить результат true
для points_into_buffer(&a, &b, 1)
.
Он может быть реализован как цикл:
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;
}
Однако компиляторы не могут оптимизировать этот цикл.
Есть ли допустимый способ записи, где с включенными текущими компиляторами и оптимизациями результат определяется в постоянное время?