Как получить 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