6

According to cppreference and this answer, C++ should not automatically generate a move constructor if there is a user declared destructor. Checking this in practice with Clang, however, I see an auto-generated move constructor. The following code prints "is_move_constructible: 1":

#include <iostream>
#include <type_traits>

struct TestClass
{
  ~TestClass()
  {}
};

int main( int argc, char** argv )
{
  std::cout << "is_move_constructible: " << std::is_move_constructible<TestClass>::value << std::endl;
}

Am I misunderstanding "there is no user-declared destructor" or std::is_move_constructible? I'm compiling with '-std=c++14' and Apple LLVM version 7.0.2 (clang-700.1.81).

Community
  • 1
  • 1

2 Answers2

8

Types without a move constructor, but with a copy constructor that accepts const T& arguments, satisfy std::is_move_constructible and implicitly-declared copy constructor has the form T::T(const T&).

If implicitly-declared copy constructor is deleted, std::is_move_constructible is not satisfied as below.

#include <iostream>
#include <type_traits>

struct TestClass
{
  ~TestClass() {}
  TestClass(const TestClass&) = delete;
};

int main( int argc, char** argv )
{
  std::cout << "is_move_constructible: " << std::is_move_constructible<TestClass>::value << std::endl;
}
Alper
  • 12,860
  • 2
  • 31
  • 41
2

For C++11 code, the accepted answer by @Alper is fine. But to make your code future-proof, note that as of Clang 3.7 (no idea which Apple version that corresponds to, sure you can find out), using -std=c++1z -Wdeprecated will generate the following

warning: definition of implicit copy constructor for 'TestClass' is deprecated because it has a user-declared destructor [-Wdeprecated]
  ~TestClass()
  ^

Live Example

The relevant part of the draft C++1z Standard N4567 is

12.8 Copying and moving class objects [class.copy]

7 If the class definition does not explicitly declare a copy constructor, a non-explicit one is declared implicitly. If the class definition declares a move constructor or move assignment operator, the implicitly declared copy constructor is defined as deleted; otherwise, it is defined as defaulted (8.4). The latter case is deprecated if the class has a user-declared copy assignment operator or a user-declared destructor.

Deprecated means that a future Standard may stop generating an implicit copy constructor in case of a user-declared destructor. It's best practice to change your code today to not rely on deprecated behavior (i.e. in this case, making the copy-behavior of your class explicit).

TemplateRex
  • 69,038
  • 19
  • 164
  • 304
  • My clang version is `clang version 5.0.0-3~16.04.1 (tags/RELEASE_500/final)`. And I use the options `-std=c++1z -Wdeprecated` too, but it doesn't give me any warnings. – chaosink Aug 24 '18 at 15:19