Since the value_type of map<S,T> is pair< const S, T >, I have
to wonder what assignability of the key-type would buy us in
_any_ possible implementation.
I never said that it would buy us anything. I can't imagine a
reasonable implementation which would use it. But at least
through C++03, it's formally a requirement.
If I've understood correctly (but it's something I've not really
paid too much attention to, so I could easily be wrong here),
assignment is not necessary for any reasonable implementation of
any of the node based types (all of the associative containers,
plus std::list---and the unordered containers as well, I think),
and the requirement for it will be dropped in the next version
of the standard. (But verify with a more reliable source before
counting on it.)
Well, I don't know what is more idiomatic. I routinely define
operator< or specialize std::less<> just so that my type can
be used transparently in sets and maps. In fact, I think, the
compiler should just provide a default like lexicographic
ordering along members.
The problem with this, IMHO, is that < already has a more or
less established meaning in the minds of the reader. Long
before the STL, for example, my bit vector based set types
overloaded the relational operators for subsets: a < b meant
that a was a strict subset of b. And while I rather think that
one could qualify this as operator overloading abuse, I don't
think it's really cut and dried---my users found it natural, at
any rate. Of course, the subset relationship is *not* an
acceptable ordering for the STL. When the STL was adopted, I
provided a separate ordering relationship for it. At the other
end of the spectrum, the standard does (correctly, IMHO) not
provide relational operators for complex---I'm sure the idea of
applying < to complex numbers would shock a mathematician.
IMHO, the general rule should be that < corresponds to something
that a normal reader would call less that, and that if the type
doesn't have a natural, undisputed ordering, then < should not
be defined. And that except for strings and ordered numeric
types, the user will normally specify the ordering to be used
for std::set. I'm not opposed, however, to providing an
arbitrary ordering by means of a specialized type for this.
When I start using hash maps, I will also routinely provide a
hash function.
That's different. A hash function is, by definition, a hash
function. < is not an arbitrary strict ordering function, it
expresses a different relationship.
I don't think that std::less<T> has to be natural. That it is
useful is entirely sufficient for me.
I don't think I'd mind a specialization of std::less<T>, IF the
class doesn't define operator<. (And there's the precedence for
pointers.) Anytime the results of a < b are defined, however, I
rather think that that's what std::less should return, to avoid
confusion. Thus, it's not an option for my bitmapped sets.
More generally, what's the problem with having to specify the
ordering function? (I don't think I've ever used std::set
without specifying it. With std::map, I'd guess that 90% of the
time, the key is std::string, but if it's neither std::string or
a built-in numeric type, I tend to specify it as well.)