[Bug c++/57064] [clarification requested] Which overload with ref-qualifier should be called?
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57064 --- Comment #14 from Thiago Macieira thiago at kde dot org 2013-04-26 06:16:04 UTC --- Understood. The idea is that one would write: QString str = QString(%1 %2).arg(42).arg(43);
[Bug c++/57064] [clarification requested] Which overload with ref-qualifier should be called?
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57064 --- Comment #15 from Jonathan Wakely redi at gcc dot gnu.org 2013-04-26 08:12:36 UTC --- That will also work if you return an rvalue, not an rvalue reference, and will be safe against accidental misuse.
[Bug c++/57064] [clarification requested] Which overload with ref-qualifier should be called?
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57064 --- Comment #16 from Thiago Macieira thiago at kde dot org 2013-04-26 13:45:35 UTC --- Thanks for the hint. However, returning an rvalue, even if moved-onto, will generate code for the destructor. It's not a matter of efficiency, just of code size. Anyway, I'll do some benchmarks, after I figure out how to work around the binary compatibility break imposed by having the in the function that already existed.
[Bug c++/57064] [clarification requested] Which overload with ref-qualifier should be called?
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57064 --- Comment #4 from Marc Glisse glisse at gcc dot gnu.org 2013-04-25 06:19:35 UTC --- (In reply to comment #0) Now suppose the following function: void g(A a) { a.p(); } Which overload should GCC call? This is my request for clarification. I couldn't find anything specific in the standard that would help explain one way or the other. Intuitively, it would be the rvalue overload, but gcc calls the lvalue overload instead. As you note in a further comment, a named rvalue reference acts as an lvalue. Making it: std::move(a).p(); Does not help. It does for me...
[Bug c++/57064] [clarification requested] Which overload with ref-qualifier should be called?
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57064 --- Comment #5 from Marc Glisse glisse at gcc dot gnu.org 2013-04-25 06:34:03 UTC --- (In reply to comment #4) (In reply to comment #0) Making it: std::move(a).p(); Does not help. It does for me... Note that I only tested 4.9, it could be something missing in the backport.
[Bug c++/57064] [clarification requested] Which overload with ref-qualifier should be called?
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57064 --- Comment #6 from Thiago Macieira thiago at kde dot org 2013-04-25 06:51:33 UTC --- void f(A a) { std::move(a).p(); } _Z1fO1A: .cfi_startproc jmp _ZNR1A1pEv@PLT # .cfi_endproc Then this looks like a bug in 4.8.1. But then are we in agreement that a.p() in that function above should call the lvalue-ref overload? It does make the feature sligthly less useful for me. It would require writing: return std::move(std::move(std::move(std::move(QString(%1 %2 %3 %4) .arg(42)) .arg(47)) .arg(-42)) .arg(-47));
[Bug c++/57064] [clarification requested] Which overload with ref-qualifier should be called?
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57064 --- Comment #7 from Marc Glisse glisse at gcc dot gnu.org 2013-04-25 07:08:07 UTC --- (In reply to comment #6) void f(A a) { std::move(a).p(); } _Z1fO1A: .cfi_startproc jmp _ZNR1A1pEv@PLT # .cfi_endproc Then this looks like a bug in 4.8.1. Indeed, I get s/R/O/ with 4.9. But then are we in agreement that a.p() in that function above should call the lvalue-ref overload? Yes. It does make the feature sligthly less useful for me. It would require writing: return std::move(std::move(std::move(std::move(QString(%1 %2 %3 %4) .arg(42)) .arg(47)) .arg(-42)) .arg(-47)); Why? You are not naming those return values, so they are still rvalues and will use the overload. (not sure why Qstring doesn't provide a mutating interface for arg)
[Bug c++/57064] [clarification requested] Which overload with ref-qualifier should be called?
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57064 --- Comment #8 from Thiago Macieira thiago at kde dot org 2013-04-25 07:13:44 UTC --- Hmm... this might be an effect of the same bug. Can you try this on 4.9? struct A { A p() const ; A p() ; }; void f() { A().p().p(); } I get: leaq15(%rsp), %rdi #, tmp60 call_ZNO1A1pEv@PLT # movq%rax, %rdi # D.69575, call_ZNKR1A1pEv@PLT # Is this second call supposed to be to R? If it's to O, it's exactly what I need to make the feature useful.
[Bug c++/57064] [clarification requested] Which overload with ref-qualifier should be called?
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57064 --- Comment #9 from Marc Glisse glisse at gcc dot gnu.org 2013-04-25 07:28:01 UTC --- (In reply to comment #8) Is this second call supposed to be to R? If it's to O, it's exactly what I need to make the feature useful. It is O.
[Bug c++/57064] [clarification requested] Which overload with ref-qualifier should be called?
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57064 --- Comment #10 from Thiago Macieira thiago at kde dot org 2013-04-25 07:34:21 UTC --- Great! That changes everything. Now I can provide a mutating arg() overload. I'll just need some #ifdef and build magic to add the R, O overloads without removing the nil overloads that already exist (binary compatibility). It would have been nicer if the lvalue ref overload didn't get extra decoration.
[Bug c++/57064] [clarification requested] Which overload with ref-qualifier should be called?
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57064 Jason Merrill jason at gcc dot gnu.org changed: What|Removed |Added Status|UNCONFIRMED |ASSIGNED Last reconfirmed||2013-04-25 AssignedTo|unassigned at gcc dot |jason at gcc dot gnu.org |gnu.org | Target Milestone|--- |4.8.1 Ever Confirmed|0 |1 --- Comment #11 from Jason Merrill jason at gcc dot gnu.org 2013-04-25 14:42:43 UTC --- Yep, this is a bug in 4.8.1 that was fixed in 4.9 by my follow-on change * call.c (add_function_candidate): Take the address of 'this' here. (build_over_call): And here. (build_new_method_call_1, build_op_call_1): Not here. (build_user_type_conversion_1): Or here. (add_candidates): Adjust. that I thought was too risky for the branch. I'll fix this differently on the branch.
[Bug c++/57064] [clarification requested] Which overload with ref-qualifier should be called?
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57064 Jason Merrill jason at gcc dot gnu.org changed: What|Removed |Added Status|ASSIGNED|RESOLVED Resolution||FIXED --- Comment #12 from Jason Merrill jason at gcc dot gnu.org 2013-04-25 17:50:25 UTC --- Fixed.
[Bug c++/57064] [clarification requested] Which overload with ref-qualifier should be called?
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57064 --- Comment #13 from Marc Glisse glisse at gcc dot gnu.org 2013-04-26 05:05:48 UTC --- Note for Thiago: please be aware of the risks of returning an rvalue reference, as opposed to just a value. The following codes will fail at runtime: Qstring const a=QString(%1 %2 %3 %4).arg(42).arg(47).arg(-42).arg(-47); Qstring b=QString(%1 %2 %3 %4).arg(42).arg(47).arg(-42).arg(-47); for(char c : QString(%1 %2 %3 %4).arg(42).arg(47).arg(-42).arg(-47))...
[Bug c++/57064] [clarification requested] Which overload with ref-qualifier should be called?
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57064 --- Comment #1 from Thiago Macieira thiago at kde dot org 2013-04-25 00:45:00 UTC --- Here's why I'm asking: QString has members like: QString arg(int, [other parameters]) const; Which are used like so: return QString(%1 %2 %3 %4).arg(42).arg(47).arg(-42).arg(-47); // returns 42 47 -42 -47 Right now, each call creates a new temporary, which is required to do memory allocation. I'd like to avoid the new temporaries by simply reusing the existing ones: QString arg(int, [...]) const ; // returns a new copy QString arg(int, [...]) ; // modifies this object, return *this; When these two overloads are present, every other call will be to rvalue-ref and the others to lvalue-ref. That is, the first call (right after the constructor) calls arg(), which returns an rvalue-ref. The next call will be to arg(), which returns a temporary, making the third call to arg() again. I can get the desired behaviour by using the overloads: QString arg(int, [...]) const ; // returns a new copy QString arg(int, [...]) ; // returns a moved temporary via return std::move(*this); However, the side-effect of that is that we still have 4 temporaries too many, albeit empty (moved-out) ones. You can see this by counting the number of calls to the destructor: $ ~/gcc4.8/bin/g++ -fverbose-asm -fno-exceptions -fPIE -std=c++11 -S -o - -I$QTOBJDIR/include /tmp/test.cpp | grep -B1 call.*QStringD movq%rax, %rdi # tmp82, call_ZN7QStringD1Ev@PLT # -- movq%rax, %rdi # tmp83, call_ZN7QStringD1Ev@PLT # -- movq%rax, %rdi # tmp84, call_ZN7QStringD1Ev@PLT # -- movq%rax, %rdi # tmp85, call_ZN7QStringD1Ev@PLT #
[Bug c++/57064] [clarification requested] Which overload with ref-qualifier should be called?
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57064 --- Comment #2 from Thiago Macieira thiago at kde dot org 2013-04-25 00:45:39 UTC --- This was a self-compiled, pristine GCC gcc version 4.8.1 20130420 (prerelease) (GCC) trunk at 198107
[Bug c++/57064] [clarification requested] Which overload with ref-qualifier should be called?
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57064 --- Comment #3 from Thiago Macieira thiago at kde dot org 2013-04-25 00:53:20 UTC --- One more note. Given: void p(A ); void p(A ); void f(A a) { p(a); } like the member function case, this calls p(A ). It's slightly surprising at first glance, but is a known and documented case. Unlike the member function case, if you do p(std::move(a)); it will call p(A ).