简体   繁体   English

为什么std :: insert需要CopyConstructibility?

[英]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.

相关问题 为什么 std::copy() 需要 std::back_inserter 插入具有足够容量的向量? - Why does std::copy() require std::back_inserter to insert into a vector with sufficient capacity? 为什么std :: allocator :: deallocate需要一个大小? - why does std::allocator::deallocate require a size? 为什么std :: reverse需要双向迭代器? - Why does std::reverse require bidirectional iterators? 为什么std :: vector的元素需要移动构造函数? - Why does std::vector require move-constructors for its elements? 为什么std :: max_element需要ForwardIterator? - Why does std::max_element require a ForwardIterator? 为什么std原子会向堆栈插入5 - Why does std atomic insert 5 to the stack 为什么 std::unique_ptr 没有明确要求 noexcept 删除器? - Why std::unique_ptr does not explicitly require a noexcept Deleter? 为什么 std::sentinel_for 概念需要默认可构造性? - Why does the std::sentinel_for concept require default constructability? 为什么不<numeric>要求/允许 std::,但是<cmath>做?</cmath></numeric> - Why doesn't <numeric> require/allow std::, but <cmath> does? 为什么 std::sort 不要求用户指定模板类型? - why does std::sort not require the user to specify the templated types?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM