avakar
avakar

Reputation: 32655

Does std::less have to be consistent with the equality operator for pointer types?

I've bumped into a problem yesterday, which I eventually distilled into the following minimal example.

#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;
}

This particular program, when compiled using MSVC 9.0 with optimizations enabled, outputs 000. This implies that

  1. the pointers are not equal, and
  2. neither of the pointers is ordered before the other according to std::less, implying that the two pointers are equal according to the total order imposed by std::less.

Is this behavior correct? Is the total order of std::less not required to be consistend with equality operator?

Is the following program allowed to output 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;
}

Upvotes: 14

Views: 601

Answers (2)

Kornel Kisielewicz
Kornel Kisielewicz

Reputation: 57575

Seems as we have a standard breach! Panic!

Following 20.3.3/8 (C++03) :

For templates greater, less, greater_equal, and less_equal, the specializations for any pointer type yield a total order, even if the built-in operators <, >, <=, >= do not.

It seems a situation where eager optimizations lead to improper code...

Edit: C++0x also holds this one under 20.8.5/8

Edit 2: Curiously, as an answer to the second question:

Following 5.10/1 C++03:

Two pointers of the same type compare equal if and only if they are both null, both point to the same function, or both represent the same address

Something is wrong here... on many levels.

Upvotes: 13

Bo Persson
Bo Persson

Reputation: 92331

No, the result is obviously not correct.

However, MSVC is known not to follow the "unique address" rules to the letter. For example, it merges template functions that happens to generate identical code. Then those different functions will also have the same address.

I guess that you example would work better if you actually did something to i and j, other that taking their address.

Upvotes: 2

Related Questions