Why did C++ standard library name the containers map and unordered_map instead of map and ordered_map? - Programming Language Design and Implementation Stack Exchange
Are c++ std::map<string,string> ordered? - Stack Overflow
How to sort a map according to value?
c++ - How to ensure that a std::map is ordered? - Stack Overflow
Videos
The short answer: Historical reasons.
Alexander Stepanov's philosophy was always that the algorithms come first. One analogy he always liked was with mathematics. When mathematicians present their work, they generally start with the axioms and work forwards. But when they are actually developing their work, they generally start with the interesting theorems and work backwards.
It's the similar story with the Standard Template Library. He believed that the interesting algorithms come first, and the data structures and their APIs get designed around them. This was especially important if the algorithms were to be generic.
The very earliest versions of the libraries that eventually became Standard Template Library (e.g. the Ada Generic Library Linear Data Structure Packages) didn't include associative containers such as maps and multimaps. Notably, they were also not pitched to the C++ standards committee in the earliest presentations.
Since the Ada Generic Library and original Standard Template Library were designed around algorithms, the interesting algorithms were generally on containers of a single type. When you have containers of single types, it's more or less clear what an "iterator" should look like, for example.
But associative containers have two interesting types: a "key" type and a "value" type. So what does a generic algorithm "iterate" on? Keys? Key-value pairs? We know what Stepanov and Lee eventually settled on, but it had to be worked out.
And that's just the API between containers and generic algorithms. The other difficult part of the API is how a programmer should present their own user-defined types to the STL.
C++ has native syntax for overloading the less-than and equal-test operators. And these need to be implemented already to write generic sort algorithms. Programmers find it quite easy to provide a less-than comparison for their user-defined types compared to, say, a radix query, which is why "library" sort functions tend to be comparison-based rather than radix-based.
In that context, it was clear that implementing associative containers that are based on comparisons was going to be easier and less controversial than ones based on hashing. Hash tables would require designing an API for providing user-declared hash functions. Unlike comparison, C++ didn't have "native" hash function support, so it needed to be designed, and it wasn't clear what the "right" design should be.
(This is a little off track, but it's also worth noting that the research community also wasn't clear as to whether or not "generic" algorithms on hash tables should be "aware" of hash table structure in some way.)
There was an early proposal for adding hash tables to the C++ standard library, more or less tracking HP's implementation, but it was too late to make it into the C++98 standard. What happened in the mean time is that third-party vendors wrote their own hash_map/hash_set (and the multi-variants) implementations that were all broadly similar, but subtly mutually incompatible.
The Boost project was started in 1998 by members of the C++ committee, in part to be a test lab for new proposals to be added to the C++ standards library. When it came time to experiment with hash tables, in around 2003, Jeremy Maitin-Shepard chose unordered rather than hash for Boost's implementation, essentially because none of the vendors had chosen that name, so there's no chance that they would clash.
Boost's proposal eventually was adopted into TR1, and subsequently C++11.
TL;DR version:
Languages like Perl, Python, and ECMAScript started with the data structures and did the algorithms later, which is why the hash tables get the simpler names. C++ started with the algorithms and did the data structures later, which is why the ordered search trees got the simpler names.
Historical accident. map was part of the original Standard Template Library approved by ANSI/ISO in 1994. std::unordered_map was added to the C++ standard library with C++ 11.
are STL maps ordered?
Yes, a std::map<K,V> is ordered based on the key, K, using std::less<K> to compare objects, by default.
So if I iterate over it, it will iterate with the first insert string first?
No. It will iterate based on the sorted order, not the order that you inserted elements. In the case of std::string, it sorts in lexicographic order (alphabetic order).
If you want to iterate based on the insertion order, you're better off using a sequence container, such as a std::vector or a std::list.
std::maps are sorted using either the given type's operator< or using a custom comparison function/functor if one is supplied as an argument to the constructor.
So no, when you iterate over the map, the first item you get won't be the one you inserted first - it will be the one that comes first alphabetically.
Of course for your sample code that doesn't make a difference because "A" is the first key you inserted and also the first one alphabetically.
You don't have to do anything. The map will be in ascending order according to the values of the key.
Internally, the map performs a comparison between keys to order its elements. By default, it uses std::less<KEY>, which is equivalent to bool operator<(int, int) for integers. For user defined types, you have to options:
Implement a
bool operator<(const MyType&, const MyType&)implementing a strict weak ordering comparison between your user defined types. Use this if your type has a natural orderingProvide a binary functor that implements strict weak ordering, which you can pass as the 3rd template parameter to the map. Use this if your type does not have a natural ordering, or if you want to build the map with an ordering different to that used by
std::less<Key>via thebool operator<(...)from point 1.
What typically happens behind the scenes is that the map is implemented as a self-balancing binary tree, and the strict weak ordering is used to place new elements in the map, and to determine whether two elements are equal. As an aside, the same logic applies to std::set, where the key and value are one and the same.
std::map does that itself. You don't have to do anything.
By default it sorts the keys in the increasing order. If you want it to do sorting in decreasing order, then pass std::greater<T> as third template argument to std::map.
std::map<int, X> m1; //sorts key in increasing order
std::map<int, X, std::greater<int>> m2; //sorts key in decreasing order
std::map<int, X, std::less<int>> m3; //sorts key in increasing order
The default argument for third template parameter is std::less<T>, so above m1 and m3 are same types!
Demo:
#include <iostream>
#include <map>
#include <string>
int main()
{
std::cout << "\nkeys are in increasing order: \n";
std::map<int, std::string> m1;
m1[5] = "first insertion but higher key";
m1[1] = "second insertion but lower key";
for(auto const & item : m1)
std::cout << "{" << item.first <<"," << item.second << "}\n";
std::cout << "\nkeys are in decreasing order: \n";
std::map<int, std::string, std::greater<int> > m2;
m2[1] = "first insertion but lower key";
m2[2] = "second insertion but higher key";
for(auto const & item : m2)
std::cout << "{" << item.first <<"," << item.second << "}\n";
}
Output:
keys are in increasing order:
{1,second insertion but lower key}
{5,first insertion but higher key}
keys are in decreasing order:
{2,second insertion but higher key}
{1,first insertion but lower key}
Notice that in both cases the items are ordered as specified by the third template argument of std::map. The output doesn't depend on the order of insertion, rather the order of the keys!
Live demo
There is also std::unordered_map which doesn't sort elements.