https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87057
--- Comment #6 from Konstantin Kharlamov <Hi-Angel at yandex dot ru> --- (In reply to Jonathan Wakely from comment #4) > (In reply to Konstantin Kharlamov from comment #2) > > As far as such trivial optimizations concerned, I'd prefer to rely on the > > compiler figuring that out — in the end, that's why we don't write assembly, > > right? =) > > If you write "return ret;" the compiler is allowed to move from the > variable, and is allowed to use the NVRO. It's not allowed to do that if you > write "return {ret};". Hmm… But, isn't any optimization allowed that doesn't change semantic of the program? And, at the very least, if a struct have no explicit copy- and move- constructors, then replacing copy with a move wherever possible shouldn't go noticed by the program. (In reply to Jonathan Wakely from comment #5) > (In reply to Jonathan Wakely from comment #4) > > (In reply to Konstantin Kharlamov from comment #2) > > > (In reply to Jonathan Wakely from comment #1) > > > > That would require a lot of special-casing just for std::variant. > > > > > > Well, I think, in place of std::variant there could be any struct-wrapper; > > > > If you have an example with a simple struct then please show it, maybe we > > can improve that case. std::variant is hundreds of lines of complex > > metaprogramming, not a struct-wrapper. > > Given: > > #include <memory> > > struct PacketErr { > std::unique_ptr<char> failed_devices; > }; > > struct V > { > PacketErr p; > }; > > V deserialize() { > PacketErr ret; > return {ret}; > } > > GCC says: > > s.cc: In function 'V deserialize()': > s.cc:14:14: error: use of deleted function 'PacketErr::PacketErr(const > PacketErr&)' > 14 | return {ret}; > | ^ > s.cc:3:8: note: 'PacketErr::PacketErr(const PacketErr&)' is implicitly > deleted because the default definition would be ill-formed: > 3 | struct PacketErr { > | ^~~~~~~~~ > s.cc:3:8: error: use of deleted function 'std::unique_ptr<_Tp, > _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = char; _Dp = > std::default_delete<char>]' > In file included from /home/jwakely/gcc/9/include/c++/9.0.0/memory:80, > from s.cc:1: > /home/jwakely/gcc/9/include/c++/9.0.0/bits/unique_ptr.h:394:7: note: > declared here > 394 | unique_ptr(const unique_ptr&) = delete; > | ^~~~~~~~~~ > > This seems pretty damn good. > > As I said, the problem is that std::variant consists of hundreds of lines of > complex metaprogramming. When a variant<X,Y> can't be constructed from Y& > the failure happens deep inside a nested template metaprogram. It's very > difficult for the compiler to guess what outcome you expected and to print > an error explaining why that didn't happen. Oh, hmm, indeed it does print that there's a copy-constructor missing. Oh well, I think the bug can probably be closed as WONTFIX :)