auto
Тип C ++ 11 удобен, так что теперь нужно const_auto
типа тоже. Например, предположим, std::list<T> a;
, если
auto p = a.begin();
имеет тип std::list<T>::iterator
тогда хочется
const_auto p = a.begin();
был тип std::list<T>::const_iterator
, К сожалению, C ++ 11, похоже, не слышал о const_auto
, Поэтому, как можно достичь желаемого эффекта с хорошим стилем, пожалуйста?
(Для информации, соответствующий вопрос задают и отвечают здесь.)
C ++ 11 позволяет писать
const auto p = a.begin();
Тем не менее, это не делает то, что вы хотите. Это делает регулярный итератор для непостоянных данных, значение которых нельзя изменить.
Тип правой стороны a.begin()
определяется типом a
и ничем с левой стороны. Если a неконстантный, то неконстантный вариант a.begin()
будет называться. Итак, вы могли бы бросить a
к const& а затем использовать его, или вы можете сделать постоянную ссылку на и использовать это:
const auto& b = a;
auto p = b.begin();
Однако более простым подходом было бы использовать недавно представленные .cbegin () и .cend ():
auto p = a.cbegin();
Я часто нахожу полезным превратить инстансы в const
версия их типа, но я нахожу использование const_cast
быть вульгарным для этой цели (зарезервировать это для удаление const
и теперь при поиске он находит опасный код), и он слишком многословен (повторяет полный тип? Гах!)
Отсюда этот фрагмент:
template<typename T>
T const& as_const( T& t ) { return t; }
который вы затем использовали бы для решения вашей проблемы следующим образом:
auto p = as_const(a).begin();
который я считаю довольно самодокументированным.
В C ++ 11 есть шаблоны функций для контейнеров STL и массивов C. Увидеть std::begin()
а также std::end()
. К сожалению, нет аналога std::cbegin()
или же std::cend()
по какой-то причине.
Вы можете использовать эти функции, чтобы делать то, что вы хотите, хотя:
template<class T, size_t N>
T const * cbegin(T(&a)[N])
{
return &a[0];
}
template<class T, size_t N>
T const * cend(T(&a)[N])
{
return &a[N];
}
template<class T>
typename T::const_iterator cbegin(T const & container)
{
return container.cbegin();
}
template<class T>
typename T::const_iterator cend(T const & container)
{
return container.cend();
}
Последние два также могут быть объявлены как:
template<class T>
auto cbegin(T const & container) -> decltype(container.cbegin())
{
return container.cbegin();
}
template<class T>
auto cend(T const & container) -> decltype(container.cend())
{
return container.cend();
}
Оттуда вы можете сделать это:
char x[] = "ab";
auto b = cbegin(x);
auto e = cend(x);