使用容器中的自定义类包装unique_ptr

时间:2015-10-11 16:17:03

标签: c++ c++11 move unique-ptr

我在1990年开始学习我的第一个C ++课程,早在新的异常,STL和诸如此类的东西之前。现在我正在编写一个自定义C ++容器,我决定将其作为学习一些C ++ 11技术和概念的机会,尤其是unique_ptr。不幸的是,我在插入元素时遇到了移动语义(我认为)的问题。这是我试图编译的代码的一个非常简化的版本:

#include <vector>
#include <memory>

struct Key {
    int k_;
    Key() : k_(0){};
    explicit Key(int k) : k_(k){};
    Key(const Key &o) : k_(o.k_) {}
    Key(Key &&o) { k_ = std::move(o.k_); }

    Key &operator=(const Key &o) {
        k_ = o.k_;
        return *this;
    }
    Key &operator=(Key &&o) {
        k_ = std::move(o.k_);
        return *this;
    }
    int get() const { return k_; }
};

template <class T> class CustomContainer {
public:
    typedef std::pair<Key, std::unique_ptr<Key>> Record;

    CustomContainer() {}
    ~CustomContainer(){};

    bool insert(const Record &record) {
        objects.emplace_back(std::move(record));
        return true;
    }
    std::vector<Record> objects;
};

int main() {
    CustomContainer<Key> q;
    q.insert(CustomContainer<Key>::Record(Key(1), std::unique_ptr<Key>(new Key(1))));
}

我正在插入一个指向Key对象的指针以保持代码简单。在我的实际应用程序中,Key有点复杂,T不是Key,而Custom容器有更多的成员函数,但这足以突出显示问题。当我在向量中只有一个unique_ptr对象时,一切看起来都很好。一旦我添加了这对,我得到:

/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/ext/new_allocator.h:120:23: error: call to
      implicitly-deleted copy constructor of 'std::pair<Key, std::unique_ptr<Key, std::default_delete<Key> > >'
        { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
                             ^   ~~~~~~~~~~~~~~~~~~~~~~~~~~~
.
.
.

simple.cc:33:13: note: in instantiation of function template specialization 'std::vector<std::pair<Key,
      std::unique_ptr<Key, std::default_delete<Key> > >, std::allocator<std::pair<Key, std::unique_ptr<Key,
      std::default_delete<Key> > > > >::emplace_back<const std::pair<Key, std::unique_ptr<Key,
      std::default_delete<Key> > > >' requested here
    objects.emplace_back(std::move(record));
            ^
simple.cc:41:5: note: in instantiation of member function 'CustomContainer<Key>::insert' requested here
  q.insert(CustomContainer<Key>::Record(Key(1), std::unique_ptr<Key>(new Key(1))));

我尝试使用自定义类而不是一对同样的东西并得到相同的错误。无论我添加了多少std :: move(),我似乎无法让编译器调用移动构造函数而不是复制构造函数。我错过了什么?

1 个答案:

答案 0 :(得分:0)

你将const ref传递给unique_ptr,然后尝试从中复制(你只能从非const移动)。传递整个对象,然后从中移动。由于您使用临时(r值引用)进行初始化,因此会在调用站点进行隐式移动。

修复代码的修补程序在这里:

template <class T> class CustomContainer {
public:
   ...
    bool insert(Record record) { // <-- FIXED
       ...
    }
};