[英]How to efficiently insert multiple copy-constructible but not copy-assignable elements in a vector?
我有一个类型X
,它是可复制构造但不可复制分配的
struct X {
X();
X(const X&);
X& operator=(const X&) = delete; // !!
X(X&&) noexcept;
X& operator=(X&&) noexcept;
int data = 54;
};
我有两个 'X' 向量: a
和b
,我想在 a 的前面插入b
的所有a
:
void add_to_front(std::vector<X>& a, const std::vector<X>& b) {
a.insert(a.begin(), b.begin(), b.end());
}
这可以在 msvc 上按预期编译和工作,但无法在 clang 和 gcc 上编译。 我猜是由于 libc++ 和 libstdc++ 的糟糕实现需要一些东西来编译,即使它永远不会被调用(或者,更糟糕的是,它会被调用?.)。
我可以编写一个手动循环来将b
的元素放置到a
中,这将产生正确的结果,但它的复杂性是 a*b 而不是 a+b,因为每次调用emplace
都会一遍又一emplace
移动a
所有元素.
那么有没有一种有效的方法呢?
我必须承认,我不太确定libc++ 和 libstdc++ 的糟糕实现是否是问题所在。 不过,我找到了一种非常简单的方法来规避 OPs 问题:
#include <vector>
struct X {
X() = default;
X(const X&) = default;
X& operator=(const X&) = delete; // !!
X(X&&) noexcept = default;
X& operator=(X&&) noexcept = default;
int data = 54;
};
void add_to_front(std::vector<X>& a, const std::vector<X>& b) {
std::vector<X> b_(b);
a.insert(a.begin(), std::make_move_iterator(b_.begin()), std::make_move_iterator(b_.end()));
}
int main()
{
std::vector<X> a, b;
add_to_front(a, b);
}
这被接受
-std=c++11 -O2
-std=c++11 -O2
/std:c++14 /O2
@Evg查看了
std::vector::insert() 的类型要求
在 OPs 的情况下,这就是重载:
template< class InputIt > iterator insert( const_iterator pos, InputIt first, InputIt last );
和
- T 必须满足 EmplaceConstructible 的要求才能使用重载 (4,5)。
- T 必须满足 MoveAssignable 和 MoveInsertable 的要求才能使用重载 (4)。 仅当 InputIt 满足 LegacyInputIterator 但不满足 LegacyForwardIterator 时才需要。
这应该由 OPs struct X
授予。
所以,对我来说,看起来 OP 对这些投诉是正确的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.