Если возможно, обойти проблему
Использование const
переменных
Ваш пример не иллюстрирует хорошее обоснование проблемы. Просто будьте более «агрессивными» с постоянством, и оно исчезнет. Вы вообще не меняете employees
, поэтому правильное решение - объявить его const
в первую очередь:
const EmployeeTitles employees = ...;
Это даже безопаснее, потому что он предотвращает изменения в employees
где угодно, а не только через итератор.
Используйте область видимости для разделения постоянного / неконстантного кода
Что если вы не можете сделать employees
const, потому что вы можете заполнять его только по частям; например, потому что вы извлекаете информацию из базы данных? Переместите заполненный код в функцию конструктора. Или для простых случаев используйте немедленно вызванную лямбду:
const EmployeeTitles employees = [] {
EmployeeTitles employees;
for (const auto& record : database.employees()) {
// Probably some more processing would be done here in the real world.
employees.emplace(record.name(), record.job_title());
}
return employees;
}();
Использование const
функций-членов
Если employees
является переменной-членом класса и вы перебираете ее в функции-члене, сделайте эту функцию const
.
Как правило
Всякий раз, когда вы сталкиваетесь с этой проблемой или чем-то подобным, подумайте о способах использования const
переменных / функций и / или области видимости, чтобы вообще обойти ее. Это позаботится о большинстве случаев.
Что если вы наткнетесь на него?
В этом случае я бы выбрал вариант 1: Явное объявление итератора const_iterator
в сочетании с объявлением using
для типа карты. Это сжато, читабельно, сразу понятно и самый прямой способ выразить свое намерение.
Другие решения, которые манипулируют с константой employees
, не так хороши, потому что это не то, что вас действительно волнует. То, что вы на самом деле хотите, это итератор только для чтения. Игра с константой employees
- это всего лишь окольный путь к достижению этой цели. И окольный код сложнее понять.
С другой стороны, это не значит, что у вас возникнут огромные проблемы с ясностью. Особенно std::as_const
приятно и лаконично.
Однако при использовании кодовой базы до C ++ 17 вам придется использовать const_cast
. Это доброкачественный, потому что добавляет const, и это не слишком многословно. Но я бы избегал этого по общему принципу, что на первый взгляд видеть const_cast
в куске кода всегда немного страшно. Другая хорошая возможность, как отметил @Swift в комментариях, - реализовать собственную версию as_const
.