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

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

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

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

В то же время текущий стандарт не имеет «законного» решения для этого, но cast_ size_t работает.

Обновление для обновления: ну, я буду gobsmacked! Не только

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

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

 std::map myMap; 

также.

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

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

20.3.3/8 в C ++ 03

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

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


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

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

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

Хорошо:

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

Это не определено:

 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 compare; bool b = compare(&x0, &x1); 

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

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

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

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

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

  • Как получить все подмножества массива?
  • Аутентификация на основе токена в веб-API без какого-либо пользовательского интерфейса
  • Динамические строки MVC 5 с BeginCollectionItem
  • самый быстрый (с низкой задержкой) метод для Inter Process Communication между Java и C / C ++
  • Представление больших чисел в исходном коде для удобочитаемости?
  • Значение параметра таблицы хранимых процедур Entity Framework
  • Почему не рекомендуется использовать рекурсивное наследование для реализации std :: tuple?
  • fstream не создаст файл
  • Как автоматически преобразовать строго типизированный enum в int?
  • Как не сериализовать свойство __type на объектах JSON
  • Что такое ObservableCollection в .net?
  • Давайте будем гением компьютера.