Выведенный тип "auto it = unordered_map.find(ключ)"?

С появлением С++ 11 у нас есть unordered_map.cbegin/cend, чтобы специально вернуть нам значения const_iterator. поэтому выведенный тип "it" в выражении "auto it = unordered_map.cbegin()" является const_iterator.

Однако, когда дело доходит до функции unordered_map.find(key), я думаю, что может отсутствовать символ "cfind()", который в частности возвращает const_iterator.

Некоторые говорят, что мы можем использовать "const auto it = unordered_map.find(key)" для получения "итератора констант", но у меня есть сильное подозрение, что "const iterator" - это один и тот же "const_iterator" , где "const итератор" ограничивает возможность изменения самого итератора, а "const_iterator" ограничивает возможность изменения содержимого, на которое ссылается итератор.

Итак, действительно, если мы хотим полностью использовать вычет типа "auto" (со знанием путаницы или вариаций "автоматического" типа дедукции - auto, auto &, const auto &, и т.д.), как я могу получить unordered_map.find(key), чтобы вернуть "const_iterator" без необходимости явно указывать "const_iterator" - что после всего наилучшего варианта использования для auto!

Ниже приведен простой пример кода, демонстрирующий поведение компилятора:

#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;
}
</int,></unordered_map>
2 ответа

Я не знаю ни одного места, где требуется const_iterator, где вы не могли бы просто передать iterator вместо этого, поэтому этот недостаток не может сильно мешать повседневной написанию кода. Тем не менее, я предпочитаю использовать const_iteratorconst в целом) везде, где мне не нужно мутировать, в интересах общего общения, поэтому я думаю, что добавление cfind() может быть полезным дополнением к будущему стандарту библиотека.

Я думаю, что этот код мог бы работать как простейшее решение для того, чего вы пытаетесь достичь:

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

Это простая функция обтекания, похожая в стиле move() и forward<t>()</t>, для предоставления (и документирования) ограничения на индивидуальное использование объекта. Затем вы можете использовать его следующим образом:

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

Это также можно использовать вместо того, чтобы наклоняться на cbegin() и cend(). Или он может использоваться в цикле, основанных на диапазонах:

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

В приведенном выше примере цикла, хотя я обычно предпочитаю auto const &element : ..., я считаю, что это было бы необязательно, и element все равно будет выведено как ссылка const.


Это немного недостаток; мы имеем cbegin и cend, но не соответствующие cfind и т.д.

Я бы предложил использовать служебную функцию, чтобы получить ссылку на const для объекта, в соответствии с ответом заставляя использовать cbegin()/cend() в диапазоне для:

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

licensed under cc by-sa 3.0 with attribution.