我基本上有这样的东西(我更改了变量名称,如果看起来很奇怪,抱歉)
#include <stack>
#include <memory>
#include <vector>
struct Sequence {
std::stack<std::unique_ptr<int>> numbers;
// It works if I change it to this
//std::stack<std::unique_ptr<int>, std::vector<std::unique_ptr<int>>> numbers;
Sequence(const std::vector<int> &v) {
for (int i : v) {
numbers.push(std::make_unique<int>(i));
}
}
};
int main() {
// constructing alone works fine
// Sequence s{{3, 1, 5}};
// but pushing it into a vector gives an error
std::vector<Sequence> ts;
ts.emplace_back(std::vector<int>{1, 5, 2});
return 0;
}
编译给出了这个错误:/usr/include/c++/10/bits/stl_uninitialized.h:137:72: error: static assertion failed: result type must be constructible from value type of input range
137 | static_assert(is_constructible<_ValueType2, decltype(*__first)>::value,
当我尝试将 Sequence 放入 vector 中时。但是,如果我将底层堆栈容器从 std::deque
更改为 std::vector
,它会起作用。我的猜测与移动和复制 unique_ptr
有关,但我真的不明白其中的细微差别——有人知道发生了什么吗?
最佳答案
这似乎是 std::vector
旧的“move if noexcept”问题的一个实例。简而言之,std::vector<Sequence>::push_back
可能需要重新分配,在这种情况下,它会使用 Sequence
的复制构造函数,因为它无法证明移动构造函数不会抛出异常。为了强制它使用移动构造函数,您必须将 Sequence
的复制构造函数标记为已删除:
Sequence(const Sequence&) = delete;
Sequence(Sequence&&) = default;
这应该使您的代码编译。当堆栈的底层容器更改时问题消失的原因是
std::vector
是 noexcept 可移动的,而 std::deque
可能不是(并且,在您似乎正在使用的 libstdc++ 中,它不是)。这个 noexcept-movability 属性由包含的 std::stack
传播到 Sequence
的隐式移动构造函数。因此,使用底层 vector
, Sequence
将自己宣传为 noexcept-movable ,并且封闭的 vector
做正确的事情。对于底层双端队列, Sequence
将自己宣传为 not-noexcept-movable,封闭的 vector
实例化复制构造函数,并且实例化失败,因为它需要 unique_ptr
的复制构造函数。
关于c++ - "result type must be constructible from value type of input range"尝试将 stack<unique_ptr>(或 deque)插入 vector 时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64758775/