Ссылочные квалификаторы и удаленные методы-члены

Рассмотрим следующий код:

#include<utility>

struct S {
void f(int) = delete;
void f(int) && { }
};

int main() { }

Это не компилирует, говоря, что метод member не может быть перегружен и это имеет смысл, конечно.

С другой стороны, следующий код компилируется:

#include<utility>

struct S {
void f(int) & = delete;
void f(int) && { }
};

int main() {
S s;
// s.f(42); <-- error, deleted member method
std::move(s).f(42);
}

Это правовой кодекс?
Разве нельзя было бы определить два совершенно разных интерфейса в одном и том же классе, первый из которых будет использоваться с lvalues, а второй — с rvalue?
Помимо того, что это не имеет особого смысла, но это действительно причиняет мне боль.
Не следует ли удалять удаленную функцию целиком, а не удаляется только если вы lvalue?
Какова цель этой функции? Это классический неясный уголок или что-то еще, чего я не вижу?

4

Решение

Иногда имеет смысл запретить определенные операции, если объект l- или же г-значение.

Вообразите обертку RAII для FILE*, Он открывает файл в конструкторе, закрывает его в деструкторе, превращая функцию C, требующую ручного управления, в класс C ++, безопасный для исключений. Для взаимодействия с интерфейсом C существует .get() член, который возвращает необработанный указатель. Кто-то может написать:

FILE* file = CFile("file.txt").get();

Это скомпилируется, но это неправильно: файл будет закрыт, как только file переменная будет инициализирована. Если вы удалите перегрузку r-значения (в первую очередь, никогда не предоставите ее), то это приведет к ошибке во время компиляции и избавит нас от поиска ошибок.

6

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

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector