Search code examples
c++clangmove-semanticsgcc-warningmove-constructor

Why does clang complain about a deleted move ctor when I don't move anything?


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.


Solution

  • 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.