[英]Why does std::insert require CopyConstructibility?
Why doesn't this code work? 为什么此代码不起作用? There is nothing about CopyConstructibility in the docs for the insert method of std::map: http://en.cppreference.com/w/cpp/container/map/insert
对于std :: map的insert方法,文档中没有关于CopyConstructibility的内容: http ://en.cppreference.com/w/cpp/container/map/insert
I can construct std::pair with the second element being my non_copyable class, but I cannot insert it into map, even though the very first overload of the insert method takes a const value_type&, so this should work fine. 我可以构造std :: pair,第二个元素是我的non_copyable类,但是即使insert方法的第一个重载采用const value_type&,也无法将其插入到map中,所以应该可以正常工作。
Can someone help me understand why std::map requires this CopyConstructibility? 有人可以帮助我了解为什么std :: map需要此CopyConstructibility吗?
#include <utility>
#include <map>
struct non_copyable {
non_copyable(){}
private:
non_copyable(const non_copyable&);
};
int main() {
std::pair<int, non_copyable> p; // this works!
std::map<int, non_copyable> m;
m.insert(std::pair<int, non_copyable>()); // this does NOT work
}
EXAMPLE: https://wandbox.org/permlink/r3H6CqehfqnHPXDL 示例: https : //wandbox.org/permlink/r3H6CqehfqnHPXDL
... even though the very first overload of the insert method takes a const value_type& , so this should work fine.
...即使insert方法的第一个重载采用const value_type& ,所以也可以正常工作。
No, actually in this case, the correct overload resolution candidate for: 不,实际上,在这种情况下,正确的过载解决方案候选对象是:
m.insert(std::pair<int, non_copyable>());
is this overloaded member function: 这是重载的成员函数:
template< class P >
std::pair<iterator,bool> insert( P&& value );
Now this page describes why this doesn't work: 现在, 此页面描述了为什么它不起作用:
... only participates in overload resolution if
std::is_constructible<value_type, P&&>::value == true
....仅在
std::is_constructible<value_type, P&&>::value == true
参与重载解析。
Your non_copyable
is not constructible: 您的
non_copyable
不可构造:
using M = std::map<int, non_copyable>;
using P = std::pair<int, non_copyable>;
std::is_constructible<M::value_type, P&&>::value; // false
because there's no available constructor including a default, implicit move constructor generated by the compiler. 因为没有可用的构造函数,包括由编译器生成的默认隐式move构造函数。
The reason non_copyable
even disabled its default, implicit move constructor is because of having a user-defined copy constructor, as documented : non_copyable
甚至禁用其默认的隐式move构造函数的原因是,由于具有用户定义的副本构造函数,如文档所述 :
If no user-defined move constructors are provided for a class type (struct, class, or union), and all of the following is true:
如果没有为类类型(struct,class或union)提供用户定义的move构造函数,则以下所有条件均成立:
there are no user-declared copy constructors
没有用户声明的副本构造函数
there are no user-declared copy assignment operators
没有用户声明的副本分配运算符
there are no user-declared move assignment operators
没有用户声明的移动分配运算符
there are no user-declared destructors
没有用户声明的析构函数
Now giving non_copyable
a move constructor becomes your responsbility: 现在给
non_copyable
一个move构造函数成为您的责任:
struct non_copyable {
non_copyable(){}
non_copyable(non_copyable &&) = default;
private:
non_copyable(const non_copyable&);
};
You may be interested why you have to make any copies at all hence provide copy constructible types even if you could construct a pair directly (emplace it) inside of a map. 您可能会感兴趣,为什么您根本不需要制作任何副本,因此即使您可以在地图内部直接构造(成对)对,也要提供可构造副本的类型。
It is because to provide the required performance the internal representation of the std::map is usually implemented as a balanced binary search tree (eventually as another data structure with similar performance characteristics) requiring some specific order of stored elements. 这是因为要提供所需的性能,通常将std :: map的内部表示形式实现为平衡的二进制搜索树(最终作为具有相似性能特征的另一个数据结构),这需要存储元素的某些特定顺序。 So after adding or deleting some elements the order may be broken and to preserve its correctness occasional internal moves of the stored elements will be needed.
因此,在添加或删除某些元素之后,该顺序可能会中断,并且为了保持其正确性,有时需要存储的元素进行内部移动。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.