Derived type "auto it = unordered_map.find (key)"?

With the advent of C ++ 11, we have unordered_map.cbegin / cend to specifically return us const_iterator values. therefore, the deduced type "it" in the expression "auto it = unordered_map.cbegin ()" is const_iterator.

However, when it comes to the unordered_map.find (key) function, I think there may be no "cfind ()" character, which in particular returns const_iterator.

Some say that we can use "const auto it = unordered_map.find (key)" to get a "constant iterator", but I have a strong suspicion that the "const iterator" is the same "const_iterator", where " The const iterator "limits the ability to change the iterator itself, and the" const_iterator "limits the ability to change the contents that the iterator refers to.

So, really, if we want to fully use the deduction of type "auto" (with knowledge of the confusion or variations of the "automatic" type of deduction - auto, auto &, const auto &, etc.), how can I get unordered_map.find ( key) to return "const_iterator" without having to explicitly specify "const_iterator" - which, after all the best use case for auto!

The following is a simple code example that demonstrates 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; } 
+6
source share
2 answers

I don’t know a single place where const_iterator is required, where you couldn’t just pass iterator instead, so this flaw cannot greatly interfere with everyday code writing. However, I prefer to use const_iterator (and const in general) wherever I need to mutate, in the interest of general communication, so I think adding cfind() might be a useful addition to the future library standard.

I think this code could work as the simplest solution for what you are trying to achieve:

 template<typename T> auto use_as_const( T const &t ) -> T const & { return t; } 

This is a simple wrap function, similar in the style of move() and forward<T>() , to provide (and document) restrictions on the individual use of an object. Then you can use it as follows:

 auto it1 = use_as_const( umii ).find(0); 

It can also be used instead of leaning on cbegin() and cend() . Or it can be used in a range based loop:

 for ( auto &element : use_as_const( some_vector_of_string ) ) { cout << element; // element = ""; // This line shouldn't compile. } 

In the above loop example, although I usually prefer auto const &element : ... , I believe that this would be optional, and element would still be output as a const reference.

+2
source

This is a bit of a drawback; we have cbegin and cend , but not matching cfind , etc.

I would suggest using a utility function to get a const reference for an object, in accordance with the answer forcing to use cbegin () / cend () in a range for :

 template<typename T> constexpr const T &as_const(T &t) { return t; } auto it1 = as_const(umii).find(0); it1->second = 42; // fails 
+1
source

Source: https://habr.com/ru/post/952232/


All Articles