As far as I know we should never compare two const character strings using relational operators <>
... because the fact that it compares the addresses rather than the values:
const char* sz1 = "Hello";
const char* sz2 = "hello";
if(sz1 < sz2);// not valid. So use strcmp instead.
map, multimap, set, multiset
impose a restriction on their key
so that the key should some how be compared to order the elements in the container. The default operator for the key is <
operator.Everything is clear until I've created a map, set
of const char*
then I get the results incorrect:
std::set<const char*> scp{ "Hello", "World", "C++", "Programming" };
std::set<std::string> sstr{ "Hello", "World", "C++", "Programming" };
// error
std::copy(scp.cbegin(), scp.cend(), std::ostream_iterator<const char*>(std::cout, " "));
std::cout << std::endl;
// Ok
std::copy(sstr.cbegin(), sstr.cend(), std::ostream_iterator<std::string>(std::cout, " "));
std::cout << std::endl;
It is apparent that scp
compares pointers to character strings while sstr
is Ok as long as class string
has defined <
to work properly.
Why STL allows this? (creating associative containers whose key element type is a char*
) and why here's even no warning?
The default operator for the key is
<
operator.
This is not true. The default comparison operator for the non-hashed associative containers is std::less
. std::less
uses operator <
for comparisons, but with one key difference. Unlike the pointers built in operator <
where
neither pointer is required to compare greater than the other.
std::less
has that the
specializations for any pointer type yield a strict total order that is consistent among those specializations and is also consistent with the partial order imposed by the built-in operators
<
,>
,<=
,>=
.
So this is a safe operation and we can reliably store pointers in the map.