4 ms·
Interesting - that prevents one of the two cases. Given fn(const Foo&) (or fn(Foo&)), your implementation would stop fn(move(x)) from compiling. But given fn(
by quietbritishjim 4y ago
Interesting - that prevents one of the two cases.
Given fn(const Foo&) (or fn(Foo&)), your implementation would stop fn(move(x)) from compiling.
But given fn(Foo) and const Foo x, your implementation would still allow fn(move(x)) to compile and perform a copy.
- gpderetta 4y agoThe Foo& case won't compile. Const foo& will as temporaries can bind to const references; this is desirable and x is still moved from. The plain Foo case won't do any copies because of NRVO and temporary elision (both optimizations are now guaranteed by the standard); again x will be moved from. The upside of this implementation is that x is always moved from. The downside is that sometimes more objects are created (for example in the const&) than the pure cast case and can't always be reliably optimized out.
- quietbritishjim 4y ago> The Foo& case won't compile. Const foo& will [compile] Not true. Both Foo& [1] and const Foo& [2] parameter types fail to compile (in gcc 8.5, I also tried gcc 10 with same result). Bizarrely, in more modern compilers, including gcc 11, both Foo& [3] and const Foo& [4] do compile, even with the language version forced to C++11. I'm very curious to know why; presumably there's some defect report that got retroactively applied to all standards, but I can't find anything relevant. In any case, this illustrates how cryptic the C++ rvalue rules are. [1] https://godbolt.org/z/97Yse4jWY https://godbolt.org/z/97Yse4jWY [2] https://godbolt.org/z/Gsj83zes6 https://godbolt.org/z/Gsj83zes6 [3] https://godbolt.org/z/xWhG9cxKn https://godbolt.org/z/xWhG9cxKn [4] https://godbolt.org/z/xadn7Txh4 https://godbolt.org/z/xadn7Txh4 > Const foo& will as temporaries can bind to const references; this is desirable and x is still moved from. Well that (it's desirable) is your opinion! In my view, in an ideal world, f(move(x)) would not mean there is at least one move... it would mean there are at most zero copies.
- gpderetta 4y agoIt doesn't compile because the code is wrong :). I forgot remove reference for the T in the result type and in the return statement. Interestingly it compiles with gcc-12 for some reason. In generic code you do want to copy if T is not movable (for example when implementing a container). The annoying thing with the existing std move is that it might or might not move from the x depending on the implementation of the sink. This implementation will always move from if x is movable. Different tradeoffs. Now can we make a move with your requirements (only move no copy?) I think so. Let me think about it.