我基本上有这样的东西(我更改了变量名称,抱歉,如果看起来很奇怪)
#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;
}
Run Code Online (Sandbox Code Playgroud)
编译出现这个错误:
/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,
Run Code Online (Sandbox Code Playgroud)
当我尝试将序列放入向量中时。但是,如果我将底层堆栈容器从 更改为std::deque,std::vector它就可以工作。我的猜测与移动和复制有关unique_ptr,但我不太明白其中的细微差别——有人知道发生了什么吗?
Bri*_*ian 11
这似乎是旧的“move if noexcept”问题的一个实例std::vector。简而言之,std::vector<Sequence>::push_back可能需要重新分配,在这种情况下会使用 的复制构造函数,Sequence因为它无法证明移动构造函数不会抛出异常。为了强制它使用移动构造函数,您必须将 的复制构造函数标记为Sequence已删除:
Sequence(const Sequence&) = delete;
Sequence(Sequence&&) = default;
Run Code Online (Sandbox Code Playgroud)
这应该能让你的代码编译。
当堆栈的底层容器发生更改时,问题消失的原因是std::vectornoexcept 是可移动的,而std::deque可能不是(并且,在您似乎正在使用的 libstdc++ 中,它不是)。此 noexcept-movability 属性由 的包含std::stack和直至隐式移动构造函数传播Sequence。因此,对于底层vector, 会将Sequence自己宣传为 noexcept-movable,并且封闭vector会做正确的事情。对于底层双端队列, 会将Sequence自身宣传为 not-noexcept-movable,封闭vector实例化复制构造函数,并且实例化失败,因为它需要 a 的复制构造函数unique_ptr。
| 归档时间: |
|
| 查看次数: |
5572 次 |
| 最近记录: |