Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reference qualifiers and deleted member methods

Consider the following code:

#include<utility>

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

int main() { }

It doesn't compile saying that the member method cannot be overloaded and it makes sense, of course.

On the other side, the following code compiles:

#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);
}

Is that legal code?
Wouldn't it be possible to define two completely different interfaces within the same class, the former to be used with lvalues, the latter with rvalues?
Apart from the fact that it doesn't make much sense, but it really hurts me.
Shouldn't a deleted function be deleted as a whole, instead of deleted only if you are a lvalue?
Which is the purpose of this feature? Is it the classic obscure corner case or is there something more I can't see?

like image 476
skypjack Avatar asked Mar 14 '23 07:03

skypjack


1 Answers

Sometimes it makes sense to prohibit certain operations if object is l- or r-value.

Imagine RAII wrapper for FILE*. It opens file in constructor, closes it in destructor, turning C feature requiring manual control to C++ exception-safe class. To interact with C interface, there is a .get() member which returns raw pointer. Someone might write:

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

It would compile, but it is wrong: file would be closed as soon, as file variable would be initialized. If you delete an r-value overload (on never provide it in the first place), then it would lead to compile-time error and save us from bug-hunting.

like image 156
Revolver_Ocelot Avatar answered Mar 16 '23 00:03

Revolver_Ocelot