Bug 62227

Summary: [DR535] Templated move not elided
Product: gcc Reporter: Roman Perepelitsa <roman.perepelitsa>
Component: c++Assignee: Not yet assigned to anyone <unassigned>
Status: UNCONFIRMED ---    
Severity: enhancement CC: daniel.kruegler, james.dennett, webrown.cpp
Priority: P3 Keywords: missed-optimization
Version: 4.8.0   
Target Milestone: ---   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed:

Description Roman Perepelitsa 2014-08-22 11:36:53 UTC
#include <stdio.h>

struct S {
  S(int) {}
  S(const S&) = default;   // (1)
  template <class = void>  // (2)
  S(S&& other) {
    puts("move");
  }
};

int main() {
  S s = 42;
  (void)s;
}

This program unexpectedly prints "move". The expected output is empty (move is elided).

The program prints nothing (as expected) if any of the following is done:

  - Line (1) is removed.
  - Line (2) is removed.
  - The program is compiled with clang.
Comment 1 Jonathan Wakely 2014-08-23 23:12:20 UTC
A template cannot be a move constructor and so it is not legal to elide it.

Removing line (1) means there is a move constructor implicitly declared, which will be used and can be elided.

Removing line (2) means there is a move constructor, which will be used and elided.
Comment 2 James Dennett 2014-08-24 21:31:52 UTC
> A template cannot be a move constructor

I'm with you so far.

> and so it is not legal to elide it.

I don't think that's the case (or at least, I'm not aware of any wording saying so).  C++98 effectively said so, but C++03/11/14 don't, AFAICS.  Elision applies to copying/moving, not just to copy/move constructors, and a template can be used for copying or moving.

The standard isn't very clear on this though.
Comment 3 Jonathan Wakely 2014-08-24 23:19:58 UTC
C++11 says "When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class object, even if the copy/move constructor..." which only applies to copy constructors or move constructors.


But the current draft says "even if the constructor selected for the copy/move operation"

So it does seem that elision is now allowed when the relevant constructor is a template.
Comment 4 Jonathan Wakely 2014-08-24 23:24:17 UTC
http://open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#535 changed that wording
Comment 5 Andrew Pinski 2021-08-23 00:28:37 UTC
C++17 and C++20 modes no longer print move since GCC 7.
Most likely due to the patches to implement p0135.

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0135r1.html