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 :)

Reply via email to