Ответ 1
Одна полезная функция const
заключается в том, что временные ряды могут связываться со ссылками на const
. Итак, это работает:
void foo(const int& );
foo(42); // ok
Этот временный 42
привязан к эталонному параметру функции, а его время жизни привязано к эталонному параметру.
Теперь рассмотрим std::cref()
. Цель состоит в том, чтобы пройти через это reference_wrapper
к чему-то, поэтому нам нужна базовая ссылка, чтобы остаться в живых. Если бы у нас была эта перегрузка:
template <class T>
reference_wrapper<const T> cref(const T&) noexcept;
Тогда я мог бы написать std::cref(42)
. Это будет нормально работать, я вернусь std::reference_wrapper<const int>
- за исключением того, что это будет болтливая ссылка. Нет никакого способа, чтобы этот код когда-либо работал.
Чтобы устранить эту очевидную ошибку, мы также имеем эту перегрузку:
template <class T> void cref(const T&&) = delete;
То есть мы явно удаляем (или определяем как удаляемую) перегрузку, беря любое значение r. Теперь при выполнении разрешения перегрузки эта 2-я перегрузка предпочтительнее, когда я передаю r-значение, и эта перегрузка плохо сформирована, и компилятор сообщает нам о нашей ошибке (глупо мне, я не могу сделать cref(42)
!) Вместо мне придется потратить несколько часов на gdb, пытаясь понять, почему у меня нет объекта.
Такой же процесс мышления может быть применен к любой функции. Есть некоторые неявные последовательности преобразований, с которыми вам может быть хорошо, и некоторые из них, с которыми вы определенно не в порядке, и хотите явно исключить. Для чего нужен =delete
.