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?