在容器中用自定义 class 包装 unique_ptr
Wrapping a unique_ptr with custom class in a container
我在 1990 年获得了我的第一个 C++ class,远早于你的新发明异常、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))));
我用自定义 class 而不是一对尝试了同样的事情,但得到了同样的错误。无论我添加了多少 std::move(),我似乎都无法让编译器调用移动构造函数而不是复制构造函数。我错过了什么?
您正在将 const ref 传递给 unique_ptr,然后尝试从中复制(您只能从非 const 移动)。通过整个对象,然后从那里移动。由于您正在使用临时(r 值引用)进行初始化,因此调用站点将有一个隐式移动。
修复代码的补丁在这里:
template <class T> class CustomContainer {
public:
...
bool insert(Record record) { // <-- FIXED
...
}
};
我在 1990 年获得了我的第一个 C++ class,远早于你的新发明异常、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))));
我用自定义 class 而不是一对尝试了同样的事情,但得到了同样的错误。无论我添加了多少 std::move(),我似乎都无法让编译器调用移动构造函数而不是复制构造函数。我错过了什么?
您正在将 const ref 传递给 unique_ptr,然后尝试从中复制(您只能从非 const 移动)。通过整个对象,然后从那里移动。由于您正在使用临时(r 值引用)进行初始化,因此调用站点将有一个隐式移动。
修复代码的补丁在这里:
template <class T> class CustomContainer {
public:
...
bool insert(Record record) { // <-- FIXED
...
}
};