В чем смысл использования delete для функции, не являющейся членом?

Выдержка из стандарта 20.12 [function.objects]:

template <class T> reference_wrapper<T> ref(T&) noexcept;
template <class T> reference_wrapper<const T> cref(const T&) noexcept;
template <class T> void ref(const T&&) = delete;
template <class T> void cref(const T&&) = delete;

Я привык видеть =delete в контексте функций-членов. Цель состоит в том, чтобы запретить операцию, предоставленную компилятором. Например, чтобы сделать класс не скопированным или не движимым.

В этом контексте, однако, намерение представляет собой документацию о намерении. Это правильно? Существуют ли какие-либо другие случаи, когда использование =delete для функции, не являющейся членом, желательно, предпочтительно или неизбежно?

Ответы

Ответ 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.