Как получить const_iterator с помощью auto?
Первый вопрос: можно ли "заставить" a const_iterator
использовать auto?
Например:
map<int> usa;
//...init usa
auto city_it = usa.find("New York");
Я просто хочу запросить, вместо того чтобы изменять что-либо, на которое указывает city_it
, поэтому я бы хотел, чтобы city_it
был map<int>::const_iterator
. Но, используя auto, city_it
совпадает с типом возврата map::find()
, который равен map<int>::iterator
. Любое предложение?
Ответы
Ответ 1
Извините, но я думаю, что лучшее предложение не, используя auto
вообще, поскольку вы хотите выполнить (неявно действующее) преобразование типа . auto
предназначен для вывода точного типа, который вам не нужен.
Просто напишите так:
std::map<std::string, int>::const_iterator city_it = usa.find("New York");
Как правильно указано MooingDuck, использование псевдонимов типов может улучшить читаемость и поддерживаемость вашего кода:
typedef std::map<std::string, int> my_map;
my_map::const_iterator city_it = usa.find("New York");
Ответ 2
Это не сильно отличается от конверсии в const
в сравнении с @Jollymorphic ответом, но я думаю, что наличие функции однострочного использования как это удобно:
template<class T> T const& constant(T& v){ return v; }
Это делает преобразование более привлекательным для глаз:
auto it = constant(usa).find("New York");
// other solutions for direct lengths comparision
std::map<std::string, int>::const_iterator city_it = usa.find("New York");
auto city_it = const_cast<const std::map<std::string, int>&>(usa).find("New York");
Хорошо, я бы сказал, больше не всегда лучше. Вы можете, конечно, выбрать имя функции в соответствии с вашими предпочтениями - as_const
или просто const_
- возможные альтернативы.
Ответ 3
Другая вариация с использованием auto (сохранение как изменяемой usa, так и const usa):
map<std::string, int> usa;
//...init usa
const auto &const_usa = usa;
auto city_it = const_usa.find("New York");
Если вам не нужна карта, которая может быть изменена вообще после init, есть другие варианты.
вы можете определить usa как const и инициализировать его вызовом функции:
const map<std::string, int> usa = init_usa();
auto city_it = usa.find("New York");
или используя лямбда для инициализации карты const:
const auto usa = [&]()->const map<std::string, int>
{
map<std::string, int> usa;
//...init usa
return usa;
}();
auto city_it = usa.find("New York");
Ответ 4
Чистым решением является работа с константой ссылки на изменяемую в противном случае карту:
const auto &const_usa = usa;
auto city_it = const_usa.find("New York");
Это позволит убедиться, что вы не можете изменить const_usa
и будете использовать итераторы const.
Ответ 5
Я не могу проверить это прямо сейчас, но я думаю, что это сделает трюк:
auto city_it = const_cast< const map<int> & >(usa).find("New York");
Ответ 6
С С++ 17 вы можете использовать std::as_const
следующим образом:
#include <utility>
// ...
auto city_it = std::as_const(usa).find("New York");
Ответ 7
Вы можете использовать auto для "отслеживания" типа или "вывода" типа:
// deduce
auto city_it = usa.find("New York");
// track
auto city_it = std::map<int>::const_iterator( usa.find("New York"));
Кроме того, часы - это современные переговоры по стилю в стиле С++ от Herb Sutter, которые охватывают большинство руководств по вычитанию этих типов.
https://youtu.be/xnqTKD8uD64