Должен ли std:: less быть совместимым с оператором равенства для типов указателей?

Вчера я столкнулся с проблемой, которую я окончательно переделал в следующий минимальный пример.

#include <iostream>
#include <functional>

int main()
{
    int i=0, j=0;
    std::cout
        << (&i == &j)
        << std::less<int *>()(&i, &j)
        << std::less<int *>()(&j, &i)
        << std::endl;
}

Эта конкретная программа при компиляции с использованием MSVC 9.0 с включенными оптимизациями выводит 000. Отсюда следует, что

  • указатели не равны, а
  • ни один из указателей не упорядочен перед другим в соответствии с std::less, подразумевая, что два указателя равны в соответствии с полным порядком, налагаемым std::less.

Правильно ли это поведение? Не требуется ли полный порядок std::less быть связан с оператором равенства?

Разрешено ли следующей программе выводить 1?

#include <iostream>
#include <set>

int main()
{
    int i=0, j=0;
    std::set<int *> s;
    s.insert(&i);
    s.insert(&j);
    std::cout << s.size() << std::endl;
}

Ответ 1

Кажется, что у нас стандартное нарушение! Panic!

Следуя 20.3.3/8 (С++ 03):

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

Кажется, ситуация, когда оптимизация приводит к неправильному коду...

Изменить: С++ 0x также содержит этот файл под 20.8.5/8

Изменить 2: Любопытно, что в качестве ответа на второй вопрос:

Следуя 5.10/1 С++ 03:

Два указателя одинакового типа равны тогда и только тогда, когда они оба null, обе указывают на одну и ту же функцию, или оба представляют один и тот же адрес

Здесь что-то не так... на многих уровнях.

Ответ 2

Нет, результат явно неверен.

Однако MSVC, как известно, не соблюдает правила "уникального адреса" для письма. Например, он объединяет функции шаблонов, которые генерируют идентичный код. Тогда эти разные функции будут иметь одинаковый адрес.

Я предполагаю, что ваш пример будет работать лучше, если вы действительно что-то сделали с я и j, другие, которые принимают их адрес.