C ++ 11 дал нам std::add_const
; с C ++ 17 у нас есть новая структура — std::as_const()
. Бывший просто привязывает const
перед типом, который вы предоставляете. Второй — это правильная (шаблон a) функция, а не trait типа, которая, кажется, делает то же самое — за исключением случая, когда тип является rvalue-ссылкой, и в этом случае его нельзя использовать.
Я не совсем понимаю мотивацию для предоставления std::as_const()
, Зачем нам это нужно в дополнение к std::add_const
?
«Потребность» — это сильное слово … std::as_const
существует, потому что это полезно, а не строго необходимо. Так как это функция, а не черта, мы можем использовать ее, чтобы «добавить const» к фактическому ценности а не типы.
Более конкретно: предположим, у меня есть некоторая переменная my_value
и я хочу рассматривать это как const
, но не копируйте его. До C ++ 17 мне нужно было бы написать:
static_cast<const MyType&>(my_value)
и если я не хочу указывать тип явно, это будет:
static_cast<std::add_const_t<std::remove_reference_t<decltype(my_value)>> &>(my_value)
или, если вы хотите получить грязную работу и использовать кастинг в стиле C:
(const decltype(my_value) &) (my_value)
все это раздражает и многословно.
Вместо этого с C ++ 17 сейчас пишут std::as_const(my_value)
и это все, что нужно сделать.
Заметки:
Эта функция отключена для ссылок rvalue, даже если она прекрасно работает для них. Причина в том, чтобы помочь вам избежать непреднамеренного сохранения ссылки на временное прошлое его уничтожения. Как объясняет @NicolBolas, если вы напишите что-то вроде:
for(auto &x : std::as_const(returns_container())) { /* do stuff with x */ }
затем время жизни возвращаемого контейнера заканчивается до первой итерации цикла. Очень легко пропустить!
За дополнительной (?) Информацией обращайтесь к официальному предложению этой функции полезности: P007R1, Адам Дэвид Алан Мартин и Алисдейр Мередит.
Других решений пока нет …