With the advent of C++11, we have unordered_map.cbegin/cend to specifically return us values of const_iterator. so the deduced type of 'it' in the expression "auto it = unordered_map.cbegin()" is const_iterator.
However, when it comes to unordered_map.find(key) function, I think there may be missing a "cfind()" counterpart, which returns a const_iterator specifically.
Some say that we can use "const auto it = unordered_map.find(key)" to obtain a "const iterator", but I have a strong suspicion that "const iterator" is the same "const_iterator", where "const iterator" limits the ability to change the iterator itself, while "const_iterator" limits the ability to change the content the iterator is referring to.
So, really, if we want to take advantage of "auto" type deduction fully (with the knowledge of the confusions or the variations of "auto" type deduction - auto, auto&, const auto&, etc.), how can I have unordered_map.find(key) to return a "const_iterator" without me having to explicitly specify "const_iterator" - that's after all the best use case for auto!
Below is a simple example code that demonstrates the compiler behavior:
#include "stdafx.h"
#include <unordered_map>
int _tmain(int argc, _TCHAR* argv[])
{
typedef std::unordered_map<int, int> umiit;
umiit umii;
auto it0 = umii.find(0);
it0->second = 42;
const auto it1 = umii.find(0);
it1->second = 42;
umiit::const_iterator it2 = umii.find(0);
it2->second = 42; // expected compiler error: assigning to const
return 0;
}
I'm not aware of any place that takes a
const_iterator
where you couldn't simply pass aniterator
instead, so this deficiency may not interfere much with day-to-day code writing. However, I do prefer to useconst_iterator
s (andconst
in general) wherever I don't need mutating, in the interests of general communication, so I think adding acfind()
might be a useful addition to the future standard library.I think this code could function as a simple workaround for what you're trying to achieve, though:
This is a simple casting wrapper function, similar in style to
move()
andforward<T>()
, to provide (and document) a constraint on individual usages of the object. You could then use it like this:This could also be used instead of leaning on
cbegin()
andcend()
. Or, it could be used in range-based for loops:In the above loop example, although I would generally prefer
auto const &element : ...
, I believe it would be unnecessary andelement
would still be deduced to be a const reference.It's a bit of a deficiency; we have
cbegin
andcend
but no correspondingcfind
, etc.I'd suggest using a utility function to get a const reference to the object, as per the answer to forcing use of cbegin()/cend() in range-based for: