Why can the following program not be compiled?
NB: something_t's move constructor is not noexcept.
#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_) {
}
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).
If I replace the line with the "this line" comment by std::unique_ptr<int> move_only
then the code compiles fine:
struct data_t {
something_t something;
std::unique_ptr<int> move_only;
};
Why does removing std::vector
help? It also compiles with or without std::vector
if I make the something_t
move constructor noexcept.
NB: adding noexcept
to something_t
's move constructor helps, but that's not the question.
Question is:
Why with this:
struct data_t {
something_t something;
std::unique_ptr<int> move_only;
};
does the program compile?
But with
struct data_t {
something_t something;
std::vector<std::unique_ptr<int>> move_only; // <-- this line
};
does the program NOT compile?
In fact, both std::unique_ptr<int>
and std::vector<std::unique_ptr<int>>
:
- non-copyable
- noexcept-moveable
So they have the same properties.
Update: I've tried to compare the type_traits of both variants:
data_t(vector) data_t(unique_ptr):
is_constructible: true true
is_trivially_constructible: false false
is_nothrow_constructible: true true
is_default_constructible: true true
is_trivially_default_constructible: false false
is_nothrow_default_constructible: true true
is_copy_constructible: true false
is_trivially_copy_constructible: false false
is_nothrow_copy_constructible: false false
is_move_constructible: true true
is_trivially_move_constructible: false false
is_nothrow_move_constructible: false false
is_assignable: false false
is_trivially_assignable: false false
is_nothrow_assignable: false false
is_copy_assignable: false false
is_trivially_copy_assignable: false false
is_nothrow_copy_assignable: false false
is_move_assignable: false false
is_trivially_move_assignable: false false
is_nothrow_move_assignable: false false
is_destructible: true true
is_trivially_destructible: false false
is_nothrow_destructible: true true
is_swappable: false false
is_nothrow_swappable: false false
The only difference is:
is_copy_constructible: true false
I.e., data_t
with vector
is copy-constructible, and with unique_ptr
it is not. But how can this difference affect compilation?