Why does making a virtual function pure (= 0) suppress std::is_nothrow_move_constructible?

Viewed 65

Why does this code only compile if I remove the = 0?

#include <type_traits>

struct Foo
{
    virtual ~Foo() noexcept = default;
    Foo() = default;
    Foo(Foo &&) noexcept = default;
    Foo(Foo const &) = default;
    Foo &operator =(Foo &&) noexcept = default;
    Foo &operator =(Foo const &) = default;
    virtual void foo() = 0;
};

static_assert(std::is_nothrow_move_constructible<Foo>::value);
1 Answers

Short version:
A variable of abstract type cannot be constructed. Removing the = 0 makes the class no longer abstract.

Long version:
First, I would like to simplify the question since the "nothrow" part is a (potentially confusing) red herring. Thestatic_assert still fails if "nothrow" is removed, as in

static_assert(std::is_move_constructible<Foo>::value);

The definition of std::is_move_constructible<T> leads to the definition of std::is_constructible. These combine to say that std::is_move_constructible<Foo>::value is true only when a variable of type Foo can be constructed from a value of type Foo&&. Since Foo is an abstract type (with the = 0 in its definition), this construction – in fact, construction from any collection of parameter types – is not allowed. Hence the value is false and the static_assert fails.

Related