Универсальный меньше <> для указателей в стандарте С++

Много раз мне нужен набор указателей. Каждый раз, когда это происходит, я заканчиваю тем, что пишу менее реалистичную реализацию для типа указателя - отбрасывает два указателя на size_t и сравнивает результаты.

Мой вопрос - есть ли в стандарте? Я не мог найти ничего подобного. Кажется, достаточно распространенный случай...

Обновление: кажется, что предстоящий стандарт устраняет все проблемы с меньшим количеством < > , предусмотренными для типов указателей и неупорядоченного набора. Через несколько лет этот вопрос будет спорным.

В то же время текущий стандарт не имеет для этого "законного" решения, но выполняется операция size_t.

Обновление для обновления: ну, я буду грызть! Не только

std::map<void *, int, std::less<void*> > myMap;

работает, но даже

std::map<void *, int > myMap;

.

И это в gcc 3.4.1. Я делал все эти броски ни для чего, и лифчик совершенно прав. Даже номер раздела, который он цитирует, точно совпадает с текущим стандартом. Ура!

Ответ 1

Два указателя можно сравнить с использованием объектов функции сравнения less, greater и т.д. В противном случае, используя обложку operator< и т.д., это возможно только в том случае, если указатели указывают на элементы одного и того же объекта массива или один прошлый конец. В противном случае результаты не заданы.

20.3.3/8 в С++ 03

Для шаблонов greater, less, greater_equal и less_equal специализации для любого тип указателя дает полный порядок, даже если встроенные операторы <, >, <=, >= не делают.

Нет необходимости явно специализировать и вручную кастинг на size_t: это снизит переносимость даже, поскольку отображение reinterpret_cast из указателей на целые значения является реализацией, и не требуется выдавать какой-либо порядок.


Изменить. Более подробный ответ см. этот.

Ответ 2

Нет, он недоступен. В стандарте указано, что указатели сравнимы только со встроенными операторами, когда они указывают на тот же массив или другой блок памяти. То есть, блок должен быть выделен сразу, в отличие от двух отдельных распределений, которые могут оказаться смежными друг с другом.

Это нормально:

int x[2];
bool b = &x[0] < &x[1];

Это undefined:

int x0;
int x1;
bool b = &x0 < &x1;

Это нормально:

struct foo {
  int x0;
  int x1;
};
foo f;
bool b = &f.x0 < &f.x1;

Оба значения являются членами одной и той же структуры, поэтому они принадлежат к одному и тому же блоку памяти (а именно, f).

Практически, однако, нет ничего плохого в вашем пользовательском сравнении.

Однако ваша специализированная специализация не нужна, поскольку шаблон std::less определен для указателей, очевидно. Итак, это нормально:

int x0;
int x1;
std::less<int*> compare;
bool b = compare(&x0, &x1);

Пока не указано, какой результат должен быть, но вы по крайней мере обещали получить какой-то результат, а не поведение undefined. Вы получаете полный заказ, но вы не знаете, какой заказ, пока не запустите его.

Ответ 3

Даже если вы можете подумать, что сравнение бит указателей безвредно (в конце концов, это просто адреса в памяти, верно?), есть веские причины, по которым языковой стандарт не поощряет его. Например, если у вас есть код, результаты которого зависят от относительного упорядочения указателей (например, порядок результатов зависит от порядка итерации через набор или карту указателей), результаты будут неустойчивыми: изменение версии компилятора или операционной системы релиз может изменить результаты. Воспроизводимость достаточно ценна, чтобы избежать этой неустойчивости.

Ответ 4

Сравнение указателей - довольно чреватый бизнес. Имеет смысл сравнивать указатели, если они оба указывают на один и тот же блок памяти, в противном случае операция undefined. Таким образом, A (действительный) набор указателей является довольно специализированной вещью, и нет, стандартная библиотека не имеет этого.

Ответ 5

Сравнение указателей, которые не выделены в одном блоке, это undefined, вероятно, потому, что есть модели памяти, у которых есть проблемы с ними (и они были более распространены).

Что вам нужно использовать, это unordered_set<>, который, как представляется, не требует оператора сравнения. Это в следующем стандарте С++ и доступно как заголовок Boost тем временем.

Ответ 6

Не hash_set что вам нужно? Он будет частью следующего стандарта