News for hackers. Stuff that matters.
Re:Lvalues, rvalues, glvalues, prvalues, xvalues, help (2018) by mehrdadn on Thursday April 11, 2019 @09:46AM (#19634423)
It's not what what you're asking is unreasonable in concept, but that it goes against how RAII is used in C++; it'd make more sense in a new language. Specifically the issue is that despite its name, RAII isn't merely used for resource acquisition, but also to define dynamic scopes. That means destroying an object too early (which can happen if an object is automatically moved) can cause a subsequent statement that doesn't syntactically depend on the variable holding that object to see the wrong program state. So if your compiler moved objects automatically, that'd break code that uses RAII as a dynamic scoping mechanism.

That said though, it might be cool to have an [[attribute]] for classes (maybe [[automove]]? or [[resource]]? or [[functional]] or [[dataflow]]??) that lets you declare that that a class's construction and destruction (or maybe all members... ) can be assumed to have no side-effects for clients to depend on, or something like that... if they can work it out that'd be cool. Ideally it'd mean that an automatic variable of that type can be destroyed following its last dependency in any given scope.

Re:Lvalues, rvalues, glvalues, prvalues, xvalues, help (2018) by notacoward on Thursday April 11, 2019 @10:01AM (#19634601)
> it goes against how RAII is used in C++

That's an excellent point. To be honest, I think it's a problem with how RAII is used, conflating execution scope and object lifetime in a way that makes "move" a bit of a mess. That's why I prefer explicit "defer" like some languages have. Nonetheless, it's a common and useful enough idiom that breaking it is not something to be taken lightly. Maybe it's not really a solvable problem, given the paths that C++ took years ago, but I'd say "too bad it's necessary" is even more applicable if that's the case.

Re:Lvalues, rvalues, glvalues, prvalues, xvalues, help (2018) by AnimalMuppet on Thursday April 11, 2019 @01:03PM (#19636689)
> I think it's a problem with how RAII is used, conflating execution scope and object lifetime in a way that makes "move" a bit of a mess.

It seems to me that there's a subset that is just fine. Use RIAA to, for example, take a lock and automatically release it when you leave a scope. That's not a problem, in itself. And go ahead and use move semantics, too. That's also fine.

But don't use move on an object that's doing RIAA to take and release a lock. That, in my view, is not much of a restriction, because if you think about it, that's not really a reasonable thing to want to do. That RIAA lock-taker is not the kind of object that you want to move, or even copy. Explicitly disable those actions (private copy constructor and operator, private move), and you should be good.

Or have I missed something?

Re:Lvalues, rvalues, glvalues, prvalues, xvalues, help (2018) by mehrdadn on Thursday April 11, 2019 @01:44PM (#19637172)
> if you think about it, that's not really a reasonable thing to want to do. That RIAA lock-taker is not the kind of object that you want to move, or even copy.

It actually is (at least re: moving). Tying lock acquisition to object lifetime is a Good Thing (TM), and if you wanted to extend or shrink the lifetime of that lock you should be able to do that by moving the RAII object, the same as how you could do it with a shared_ptr or whatever.

Re:Lvalues, rvalues, glvalues, prvalues, xvalues, help (2018) by notacoward on Thursday April 11, 2019 @01:40PM (#19637113)
> don't use move on an object that's doing RIAA to take and release a lock.

Absolutely. If the question is "what would I do in C++ today" then my answer is that I would use RAII subject to common-sense rules like this.

> Explicitly disable those actions (private copy constructor and operator, private move)

That's a decent enough solution within the context of C++ as an unchangeable thing, but I want people to look beyond that context. C++ has never been an unchangeable thing. Programmers shouldn't have to take such extra steps, so closely tied to how the language works that year, to get a conceptually simple result. That's how bugs creep in, and how even correct code becomes drudgery. We have no choice but to accept it now, but we shouldn't accept it permanently.

Re:Lvalues, rvalues, glvalues, prvalues, xvalues, help (2018) by Rusky on Thursday April 11, 2019 @06:01PM (#19639710)
Automatic moves don't imply that you can't use RAII to define dynamic scopes. In fact it's the reverse- moves give RAII much more power and flexibility around scopes. The problem, instead, is that C++ has no way to determine whether later statements depend on moved-from variables.

To a first approximation, this could be solved using the same analysis that powers "use of uninitialized variable warnings." In the general case you need something more powerful, like the C++ Core Guidelines lifetime checker (https://herbsutter.com/2018/09/20/lifetime-profile-v1-0-post...). This means move operations end scopes just like `}`s do, preserving both RAII and the compiler's ability to help the programmer.

Re:Lvalues, rvalues, glvalues, prvalues, xvalues, help (2018) by mehrdadn on Thursday April 11, 2019 @07:22PM (#19640317)
No, lack of good code analysis is not the problem. If the compiler was to only do a move in cases where it could prove variable independence then it would be operating under the as-if rule -- which it is already allowed to do -- and hence your code wouldn't behave any differently than if it hadn't done that. Automatic moves OTOH change the semantics of the code, which is kind of the point -- the compiler can't do an automatic move without permission unless the language specification says so, and unlike with the case of copy elision, it doesn't permit the compiler to change the semantics like this, as RAII has multiple use cases as I mentioned above that would break if this was permitted.
Re:Lvalues, rvalues, glvalues, prvalues, xvalues, help (2018) by Rusky on Thursday April 11, 2019 @07:57PM (#19640529)
Yes, we're discussing an alternative design here. An automatic move should change the semantics of the program, rendering later uses invalid.

This does not break RAII- it merely changes the defaults. It should be copies that are marked in the program source, not moves- this is unfortunately not backwards compatible, but it's also not a problem for how RAII gets used.

Re:Lvalues, rvalues, glvalues, prvalues, xvalues, help (2018) by FrankHB on Sunday April 14, 2019 @10:42AM (#19659663)
Dynamic scopes are not available in C++. I suppose them as in languages like Emacs Lisp. I get the point, though.