Рассмотрим следующий код:
#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?
Какова цель этой функции? Это классический неясный уголок или что-то еще, чего я не вижу?
Иногда имеет смысл запретить определенные операции, если объект l- или же г-значение.
Вообразите обертку RAII для FILE*
, Он открывает файл в конструкторе, закрывает его в деструкторе, превращая функцию C, требующую ручного управления, в класс C ++, безопасный для исключений. Для взаимодействия с интерфейсом C существует .get()
член, который возвращает необработанный указатель. Кто-то может написать:
FILE* file = CFile("file.txt").get();
Это скомпилируется, но это неправильно: файл будет закрыт, как только file
переменная будет инициализирована. Если вы удалите перегрузку r-значения (в первую очередь, никогда не предоставите ее), то это приведет к ошибке во время компиляции и избавит нас от поиска ошибок.
Других решений пока нет …