Why default move constructor cannot be created in this example

Viewed 45

Why the following program cannot be compiled:

#include <memory>
#include <vector>

class something_t {
public:
    constexpr something_t() = default;

    constexpr something_t(const something_t& other)
        : field_(other.field_) {
    }

    constexpr something_t(something_t&& other)
        : field_(other.field_) {
    }

    constexpr something_t& operator=(const something_t& other) {
        field_ = other.field_;
        return *this;
    }

    constexpr something_t& operator=(something_t&& other) {
        field_ = other.field_;
        return *this;
    }

private:
    unsigned int field_{ 0 };
};

struct data_t {
    something_t something;
    std::vector<std::unique_ptr<int>> move_only; // <-- this line
};

int main() {
    std::vector<data_t> result;
    data_t data;
    result.push_back(std::move(data));
    return 0;
}

Error is (within g++):

/usr/include/c++/9/bits/stl_uninitialized.h:127:72: error: static assertion failed: result type must be constructible from value type of input range
127 |       static_assert(is_constructible<_ValueType2, decltype(*__first)>::value,
    |                                                                        ^~~~~        

(nearly the same with clang and MSVC).

But any of this compiles:

1) adding noexcept to something_t(something_t&&) move constructor

2) replacing line market with "this line" with std::unique_ptr<int> move_only:

    struct data_t {
        something_t something;
        std::unique_ptr<int> move_only;
    };

3) totally removing line marked with "this line":

    struct data_t {
        something_t something;
    };

4) adding default not-noexcept constructor to data_t:

    data_t() = default;
    data_t(data_t&&) = default;

We know that the type need to be noexcept move constructable, so why do fixes 2 and 4 do that when they shouldn't?

0 Answers
Related