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.
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 <=>
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-inoperator<
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
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With