Issue
Simplified issue:
#include <stdio.h>
class X
{
public:
int a = 0;
X() { printf("constr-def %d\n", a); }
X(int i):a(i+1) { printf("constr-i %d\n", a); }
int operator=(int i) { a = i; return i; }
operator bool() { return !!a; }
//~ X(const X& o) { a = o.a; printf("copy-constr %d\n", a); };
//~ const X& operator=(const X& o) { a = o.a; printf("copy-op %d\n", a); return *this; };
X(const X& o) = delete;
const X& operator=(const X& o) = delete;
};
int main() {
X x;
X y = 5; // should be equivalent to X y(5)
printf("results: %d %d\n", x.a, y.a);
}
Output when compiled as is with MSVC; or with gcc / MSVC and non-deleted copy constructor variants active (commented out above):
>g++ -Os dede.cpp -o dede
>dede
constr-def 0
constr-i 6
results: 0 6
>Exit code: 0
--> Copy constructor is never used; MSVC compiles successfully as is.
Compile as is with gcc (v9.3.0 current mingw/msys64 build):
>g++ -Os dede.cpp -o dede
dede.cpp: In function 'int main()':
dede.cpp:20:8: error: use of deleted function 'X::X(const X&)'
20 | X y = 5; // should be equivalent to X y(5)
| ^
dede.cpp:14:5: note: declared here
14 | X(const X& o) = delete;
| ^
dede.cpp:7:2: note: after user-defined conversion: 'X::X(int)'
7 | X(int i):a(i+1) { printf("constr-i %d\n", a); }
| ^
>Exit code: 1
Why does gcc error out with use of deleted
copy constructor, when he doesn't use it in the non-deleted case?
Solution
Before C++17 such copy elision is an optimization, which is permitted but the copy (or move) constructor still must be present and accessible.
Since C++17 the code works fine because for mandatory copy elision the copy/move constructors need not be present or accessible again.
C++17 core language specification of prvalues and temporaries is fundamentally different from that of the earlier C++ revisions: there is no longer a temporary to copy/move from.
Answered By - songyuanyao Answer Checked By - Marie Seifert (WPSolving Admin)