(связанный с my previous question)Указывает ли указатели на целые числа общий порядок указателей?
В QT, то QMap
documentation говорит:
Ключ типа QMap должен предоставить
operator<()
указание общего порядка.
Однако в qmap.h
, они, кажется, использовать что-то похожее на std::less
сравнивать указатели:
/*
QMap uses qMapLessThanKey() to compare keys. The default
implementation uses operator<(). For pointer types,
qMapLessThanKey() casts the pointers to integers before it
compares them, because operator<() is undefined on pointers
that come from different memory blocks. (In practice, this
is only a problem when running a program such as
BoundsChecker.)
*/
template <class Key> inline bool qMapLessThanKey(const Key &key1, const Key &key2)
{
return key1 < key2;
}
template <class Ptr> inline bool qMapLessThanKey(const Ptr *key1, const Ptr *key2)
{
Q_STATIC_ASSERT(sizeof(quintptr) == sizeof(const Ptr *));
return quintptr(key1) < quintptr(key2);
}
Они просто бросают указатели на quintptr
с (что является QT-версия uintptr_t
, то есть , unsigned int, который способен storing a pointer) и сравнить результаты.
Следующий тип обозначает целое число без знака типа с тем свойством, что любой допустимый указатель к мочеиспусканию могут быть преобразованы к этому типу, а затем преобразуется обратно в указатель на пустоту, и результат будет сравнивать равна первоначальной указатель:
uintptr_t
Как вы думаете, эта реализация qMapLessThanKey()
на указателях в порядке?
Конечно, есть общий заказ на интегральные типы. Но я думаю, этого недостаточно, чтобы сделать вывод, что эта операция определяет общий порядок указателей.
Я думаю, что это правда, только если p1 == p2
подразумевает quintptr(p1) == quintptr(p2)
, что, AFAIK, не указано.
В качестве контрпримера этого условия представьте себе цель с использованием 40 бит для указателей; он может конвертировать указатели в quintptr
, устанавливая 40 младших битов в адрес указателя и оставляя 24 старших бита неизменными (случайными). Этого достаточно для обеспечения конвертируемости между quintptr
и указателями, но это не определяет общий порядок указателей.
Как вы думаете?
Хороший вопрос. Я думаю, вы сами ответили на это: преобразование из указателя в целое могло каждый раз давать другое значение (представьте себе 'to_int (void * p) {return to_int32 (p) + rand() << 40;}' –
Это нормально в теории, но знает ли кто-нибудь о такой платформе? – marom
Говоря о вашем примере, если указатель имеет 40 бит, а unsigned long - 64 бита, тогда будет запущен assert. – NathanOliver