6
votes
#include <type_traits>

struct test {
    virtual void foo() noexcept = 0;
};

struct test2 : test {
    void foo() noexcept override final {}   
};

// fails
static_assert(std::is_move_constructible<test>::value, "test not move constructible");
// succeeds
static_assert(std::is_move_constructible<test2>::value, "test2 not move constructible");

(Live)
According to cppreference.com (and as far as I understand), test should have an implicitly-generated move constructor:

The implicitly-declared or defaulted move constructor for class T is defined as deleted in any of the following is true:

  • T [= test] has non-static data members that cannot be moved (have deleted, inaccessible, or ambiguous move constructors)
  • T has direct or virtual base class that cannot be moved (has deleted, inaccessible, or ambiguous move constructors)
  • T has direct or virtual base class with a deleted or inaccessible destructor
  • T is a union and has a variant member with non-trivial copy constructor
  • (until C++14) T has a non-static data member or a direct or virtual base without a move constructor that is not trivially copyable.

Why does the compiler not generate an implicit move constructor for test? Any why does it do so for test2?

1

1 Answers

14
votes

std::is_move_constructible checks whether the type can be constructed from an rvalue argument. test is an abstract class type. It cannot be constructed at all, regardless of argument.