Как достичь const_auto, так как в C ++ 11 его нет?

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, Поэтому, как можно достичь желаемого эффекта с хорошим стилем, пожалуйста?

(Для информации, соответствующий вопрос задают и отвечают здесь.)

3

Решение

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();
13

Другие решения

Я часто нахожу полезным превратить инстансы в const версия их типа, но я нахожу использование const_cast быть вульгарным для этой цели (зарезервировать это для удаление constи теперь при поиске он находит опасный код), и он слишком многословен (повторяет полный тип? Гах!)

Отсюда этот фрагмент:

template<typename T>
T const& as_const( T& t ) { return t; }

который вы затем использовали бы для решения вашей проблемы следующим образом:

auto p = as_const(a).begin();

который я считаю довольно самодокументированным.

3

В 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);
2