Bug 46246 - [C++0x] Move constructor required when passing a temporary by copy, but not actually used
Summary: [C++0x] Move constructor required when passing a temporary by copy, but not a...
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.5.1
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-10-30 16:27 UTC by Alessandro Pignotti
Modified: 2010-11-01 14:17 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments
test case that fails to compile (189 bytes, text/x-c++src)
2010-10-30 16:27 UTC, Alessandro Pignotti
Details
test case that shows that the move constructor is not actually used (182 bytes, text/x-c++src)
2010-10-30 16:28 UTC, Alessandro Pignotti
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Alessandro Pignotti 2010-10-30 16:27:10 UTC
Created attachment 22208 [details]
test case that fails to compile

The attached test case causes a compiler error, GCC seems to need the unavailable move constructor even if a
Comment 1 Alessandro Pignotti 2010-10-30 16:28:49 UTC
Created attachment 22209 [details]
test case that shows that the move constructor is not actually used
Comment 2 Alessandro Pignotti 2010-10-30 16:31:27 UTC
The secondo attachment compiles, but the move constructor seems not really used. The output is:

default bar
foo called

Moreover i was expecting a call to the copy constructor but that was elided, is this an optimization or something mandated by the standard?
Comment 3 Paolo Carlini 2010-10-31 10:00:51 UTC
Let's add Jason in CC..
Comment 4 Jonathan Wakely 2010-10-31 12:05:00 UTC
Copy elision is an optimisation allowed by the standard, but not mandated.

-fno-elide-constructors to disable it, then you should see the move constructor called for the second test case.

The relevant constructor must be accessible and callable even if it is elided.
Comment 5 Paolo Carlini 2010-10-31 13:28:14 UTC
Makes sense, of course (I'm not used to private or protected deleted members). Thus looks like this can closed as invalid?
Comment 6 Alessandro Pignotti 2010-10-31 15:10:22 UTC
Please consider the first test case before declaring this bug invalid. I think should be legal to delete the move construtor and still being able to pass temporaries by copy.
Comment 7 Jonathan Wakely 2010-11-01 00:15:33 UTC
No, a deleted function can still be selected by overload resolution. Defining a move constructor as deleted does not have the semantics you want.

In the current draft, n3126, a user-declared copy constructor suppresses the implicit declaration of a move constructor.  So all you need to do to make a class copyable but not movable is declare the copy constructor.  Don't declare a move constructor, definitely don't define it as deleted.


$ cat foo.cpp
#include <iostream>

using namespace std;

class Bar
{
public:
        Bar()
        {
                cout << "default bar" << endl;
        }
        Bar(const Bar& r)
        {
                cout << "copy bar" << endl;
        }
};

void foo(Bar p)
{
        cout << "foo called" << endl;
}

int main()
{
        foo(Bar());
        return 0;
}
$ g++ -std=c++0x foo.cpp -fno-elide-constructors
$ ./a.out
default bar
copy bar
foo called
Comment 8 Jason Merrill 2010-11-01 14:17:04 UTC
Jonathan is correct.