Reputation: 403
Premise :
#include <iostream>
using namespace std;
class ABC {
public:
ABC() {
cout << "Default constructor ..\n";
}
ABC(const ABC& a) {
cout << "In copy constrcutor ..\n";
}
ABC(ABC&& aa) = delete;
};
int main(int argc, char* argv[]) {
ABC b{ABC{}};
return 0;
}
Compile this with GCC vs Clang
Clang - Apple LLVM version 8.1.0 (clang-802.0.42)
Gcc - 5.4.0 ubuntu
Observation Clang complains about deleted Move constructor.
Gcc does not complain at all. And will output correctly.
Question Why?
For gcc, I know that if you are simply initializing both lvalue and rvalue, it optimizes and does not actually call the copy constructor and copy the temporary to the lvalue.
Why does Clang differ? I thought (not sure, hence the question) this was in C++ standard, which one deviated (or not)? Or am I doing something wrong.
Compilation command : g++ --std=c++11 -O3 file.cpp
For additional fun, remove curly braces and put parenthesis instead ;)
ABC b{ABC{}};
to, ABC b(ABC());
, Unrelated to this question.
EDIT : Someone marked the question as a dup, which it is not. I clearly state that I think C++11 standard includes copy elision. However, CLANG does not seem to have the same behavior on something as critical as constructors.
HERE Is the LINK : http://en.cppreference.com/w/cpp/language/copy_elision
clearly, it says C++11. I trust cppref.
Upvotes: 3
Views: 397
Reputation: 217235
ABC{}
is a temporary, so ABC b{ABC{}}
would use move constructor (even if elision would be possible).
As move constructor is deleted you should get an error.
Your version of gcc has a bug and doesn't detect the error by a wrong elision.
In C++17, with guaranty copy elision, even deleted constructor can be elided. So, your code would compile in C++17 with only one default constructor called.
Upvotes: 8
Reputation: 6240
EDIT : Someone marked the question as a dup, which it is not. I clearly state that I think C++11 standard includes copy elision. However, CLANG does not seem to have the same behavior on something as critical as constructors.
HERE Is the LINK : http://en.cppreference.com/w/cpp/language/copy_elision
clearly, it says C++11. I trust cppref.
It was me who marked it as a dupe. From the page you linked:
Under the following circumstances, the compilers are permitted, but not required to omit the copy- and move- (since C++11)construction
When a nameless temporary, not bound to any references, would be copied or moved (since C++11) into an object of the same type (ignoring top-level cv-qualification), the copy/move (since C++11) is omitted. (until C++17)
This optimization is mandatory; see above. (since C++17)
As you can see move constructor will be required because copy elision is not a requirement but recommendation pre C++17. C++17 compilers should not complain about deleted move constructor under the same circumstance.
Upvotes: 1