Единственно правильный способ сделать это - такой подход.
template <typename T>
bool points_within_array(T* p, T* begin, T* end)
{
for (; begin != end; ++begin)
{
if (p == begin)
return true;
}
return false;
}
Совершенно очевидно, что это не сработает, если T == void
.Я не уверен, что два void*
технически определяют диапазон или нет.Конечно, если бы у вас было Derived[n]
, было бы неверно утверждать, что (Base*)Derived, (Base*)(Derived + n)
определил допустимый диапазон, поэтому я не могу видеть его действительным для определения диапазона с чем-либо, кроме указателя на фактический тип элемента массива.
Приведенный ниже метод завершается ошибкой, поскольку не указано, что <
возвращает, если два операнда не указывают на элементы одного и того же объекта или элементы одного и того же массива.(5.9 [expr.rel] / 2)
template <typename T>
bool points_within_array(T* p, T* begin, T* end)
{
return !(p < begin) && (p < end);
}
Приведенный ниже метод завершается ошибкой, поскольку также не определено, что std::less<T*>::operator()
возвращает, если два операнда не указывают на элементы одного и того же объекта или элементовтот же массив.
Это правда, что std::less
должен быть специализирован для любого типа указателя, чтобы получить общий порядок, если встроенный <
не делает, но это полезно только для использования, такого как предоставлениеключ для set
или map
.Не гарантируется, что общий порядок не будет чередовать отдельные массивы или объекты.
Например, в архитектуре с сегментированной памятью смещение объекта может использоваться для <
и в качестве наиболее значимого дифференциатора для std::less<T*>
с индексом сегмента, используемым для разрыва связей.В такой системе элемент одного массива может быть упорядочен между границами второго отдельного массива.
template <typename T>
bool points_within_array(T* p, T* begin, T* end)
{
return !(std::less<T*>()(p, begin)) && (std::less<T*>()(p, end));
}