Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does a program with std::map<T*, U> have well-defined behaviour? [duplicate]

Comparing pointers to unrelated objects has unspecified results.

That would seem to suggest that this program may have undefined behaviour, at the very least because we cannot guarantee a strict weak ordering on the key type:

#include <map>

int main()
{
    int x = 0, y = 1;
    bool arbitrary = false;

    std::map<int*, bool> m{
       {&x, arbitrary},
       {&y, arbitrary}
    };
}

More generally, then, can we say that a map with pointer keys is a dangerous* proposition? Or is there some special rule we can lean on here?

* Academically speaking, that is; in reality I'm not aware of mainstream implementations that will actually raise hell over comparing arbitrary pointers.

like image 699
Lightness Races in Orbit Avatar asked Jan 05 '20 18:01

Lightness Races in Orbit


3 Answers

Yes, because std::map default comparison operator is std::less, which, unlike the standard comparison operator, is completely defined for pointer types.

[comparisons#2]

For templates less, greater, less_­equal, and greater_­equal, the specializations for any pointer type yield a result consistent with the implementation-defined strict total order over pointers ([defns.order.ptr]).

The implementation-defined strict total order over pointers is defined in [defns.order.ptr] as:

implementation-defined strict total ordering over all pointer values such that the ordering is consistent with the partial order imposed by the builtin operators <, >, <=, >=, and <=>

like image 133
Holt Avatar answered Oct 24 '22 01:10

Holt


std::less (default comparer of std::map) has special treatment about pointer allowing that:

A specialization of std::less for any pointer type yields a strict total order, even if the built-in operator< does not.

And about

can we say that a map with pointer keys is a dangerous proposition?

So it is fine in general.

Additional precaution should be taken with const char* key:

We compare pointers and not string content (mostly beginner confusions).

C-string literals with same content have no guaranty to be equals:

"literal" == "literal"; // Not guaranteed
"literal" < "literal"; // false .. or true
like image 8
Jarod42 Avatar answered Oct 24 '22 02:10

Jarod42


std::map use std::less that have a specialization for pointer type :

A specialization of std::less for any pointer type yields a strict total order, even if the built-in operator< does not. The strict total order is consistent among specializations of std::less, std::greater, std::less_equal, and std::greater_equal for that pointer type, and is also consistent with the partial order imposed by the corresponding built-in operators (<, >, <= and >=).

For a more specific description i leave you 2 links:

std::less first link

std::less second link

like image 2
Zig Razor Avatar answered Oct 24 '22 01:10

Zig Razor