c – std :: map <> :: insert使用非可复制对象和均匀初始化

前端之家收集整理的这篇文章主要介绍了c – std :: map <> :: insert使用非可复制对象和均匀初始化前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
看看下面的代码
#include <utility>
#include <map>

// non-copyable but movable
struct non_copyable {
    non_copyable() = default;

    non_copyable(non_copyable&&) = default;
    non_copyable& operator=(non_copyable&&) = default;

    // you shall not copy
    non_copyable(const non_copyable&) = delete;
    non_copyable& operator=(const non_copyable&) = delete;
};

int main() {
    std::map<int,non_copyable> map;
    //map.insert({ 1,non_copyable() });  < FAILS
    map.insert(std::make_pair(1,non_copyable()));
    // ^ same and works
}

取消注释g 4.7上的标记行时,编译此代码段将失败.所产生的错误表示non_copyable不能被复制,但我预计将被移动.

为什么插入使用均匀初始化构造的std :: pair失败但不是使用std :: make_pair构造的?两者都不应该产生可以成功地移动到地图中的值吗?

解决方法

[这是一个完整的重写.我以前的答复与这个问题无关.]

该地图有两个相关的插入重载:

> insert(const value_type& value),和
>< template typename P>插入(P&& value).

当您使用简单的list-initializer map.insert({1,non_copyable()});所有可能的重载被考虑.但是只有第一个(占用了const value_type&),因为另一个没有意义(没有办法神奇地猜测你打算创建一个对).当然,第一个重载不起作用,因为你的元素不可复制.

您可以通过使用make_pair显式创建对象,如您已经描述的那样,或通过明确命名值类型来使第二个重载工作:

typedef std::map<int,non_copyable> map_type;

map_type m;
m.insert(map_type::value_type({1,non_copyable()}));

现在,列表初始化器知道要查找map_type :: value_type构造函数,找到相关的可移动的构造函数,结果是一个rvalue对,它绑定到插入函数的P& -overload.

(另一个选择是使用片段式构造和forward_as_tuple来使用emplace(),尽管这样会更详细一些.)

我认为这里的道德是列表初始化器寻找可行的重载 – 但是他们必须知道要寻找的内容

猜你在找的C&C++相关文章