我正在学习Boost Intrusive库。我尝试复制STL容器时遇到问题。我使用std :: vector。它包含模式list_base_hook
中的类auto_unlink
的元素,但是当您调用复制构造函数时,有关节点(is_linked()
)的信息将丢失。
我有以下代码:
class helper_class
{
public:
helper_class(void) { /* ... */ }
helper_class(const helper_class& hc) { /* ... */ }
helper_class(helper_class&& hc) { /* ... */ }
helper_class & operator=(const helper_class& hc) { /* ... */ }
helper_class & operator=(helper_class&& hc) { /* ... */ }
virtual ~helper_class(void) { /* ... */ }
// ...
};
typedef list_base_hook<link_mode<auto_unlink> > auto_hook;
class my_class : public auto_hook
{
public:
friend bool operator==(const my_class &a, const my_class &b)
{
return (a.int_ == b.int_) &&
(a.helper_class_ == b.helper_class_);
}
int int_;
helper_class* helper_class_;
// ...
};
typedef list<my_class, constant_time_size<false> > my_class_list;
struct new_cloner
{
my_class *operator()(const my_class &clone_this)
{ return new my_class(clone_this); }
};
struct delete_disposer
{
void operator()(my_class *delete_this)
{ delete delete_this; }
};
int main()
{
// ...
helper_class the_helper_class;
const int MaxElem = 100;
std::vector<my_class> nodes(MaxElem);
std::vector<my_class> copy_nodes(MaxElem);
my_class_list list;
for(int i = 0; i < MaxElem; ++i) {
nodes[i].int_ = i;
nodes[i].helper_class_ = &the_helper_class;
}
list.insert(list.end(), nodes.begin(), nodes.end());
my_class_list cloned_list;
cloned_list.clone_from(list, new_cloner(), delete_disposer());
copy_nodes = nodes;
std::cout << "nodes[0].is_linked() : "
<< ((nodes[0].is_linked()) ? "LINKED":"NO-LINKED")
<< std::endl;
std::cout << "copy_nodes[0].is_linked() : "
<< ((copy_nodes[0].is_linked()) ? "LINKED":"NO-LINKED")
<< std::endl;
std::cout << "list[0].is_linked() : "
<< (((*list.begin()).is_linked()) ? "LINKED":"NO-LINKED")
<< std::endl;
std::cout << "cloned_list[0].is_linked() : "
<< (((*cloned_list.begin()).is_linked()) ? "LINKED":"NO-LINKED")
<< std::endl;
cloned_list.clear_and_dispose(delete_disposer());
// ...
return 0;
};
标准输出:
nodes[0].is_linked() : LINKED
copy_nodes[0].is_linked() : NO-LINKED
list[0].is_linked() : LINKED
cloned_list[0].is_linked() : LINKED
为什么向量copy_nodes
没有链接?
谢谢你。
答案 0 :(得分:2)
为什么您希望复制的节点位于集合中?
如果你打印一本书两次,你是否期望它与几个月前印刷的另一本书完全在同一个图书馆?
它只是一个不同的对象。也称为副本。
如果你的副本会神奇地&#34;克隆钩子也会破坏容器不变量,或者提出问题/应该在容器中插入副本的位置。
经过一番严肃的辩论后,我认为可能想知道如何克隆列表以及向量中的值:
my_class_list cloned_list;
std::vector<my_class> cloned_nodes;
cloned_nodes.reserve(MaxElem);
cloned_list.clone_from(
list,
[&cloned_nodes](my_class const&v) { cloned_nodes.push_back(v); return &cloned_nodes.back(); },
[](my_class*){}
);
这里没有删除(因为你无论如何都可以破坏矢量)。这是
的完整演示<强> Live On Coliru 强>
#include <boost/intrusive/list.hpp>
using namespace boost::intrusive;
struct my_class : list_base_hook<link_mode<auto_unlink> > { };
typedef list<my_class, constant_time_size<false> > my_class_list;
#include <iostream>
int main()
{
const int MaxElem = 100;
std::vector<my_class> nodes(MaxElem);
//////////////////////////////////////////////
// He's making a list
my_class_list list;
list.insert(list.end(), nodes.begin(), nodes.end());
//////////////////////////////////////////////
// He's checking it twice
my_class_list cloned_list;
std::vector<my_class> cloned_nodes;
cloned_nodes.reserve(MaxElem);
cloned_list.clone_from(
list,
[&cloned_nodes](my_class const&v) { cloned_nodes.push_back(v); return &cloned_nodes.back(); },
[](my_class*){}
);
std::cout << std::boolalpha;
std::cout << "nodes[0].is_linked() : " << nodes[0].is_linked() << std::endl;
std::cout << "cloned_nodes[0].is_linked(): " << cloned_nodes[0].is_linked() << std::endl;
std::cout << "list[0].is_linked() : " << list.begin()->is_linked() << std::endl;
std::cout << "cloned_list[0].is_linked() : " << cloned_list.begin()->is_linked() << std::endl;
//////////////////////////////////////////////
// Gonna find out who's naughty or nice:
auto nit = cloned_nodes.begin();
auto lit = cloned_list.begin();
while (nit != cloned_nodes.end() && lit != cloned_list.end()) {
assert(&(*nit++) == &(*lit++)); // this would fail if you didn't `reserve()` the vector up front
}
//////////////////////////////////////////////
// now, if you really want you can do
cloned_list.clear();
// after which the simplest thing to do would be `cloned_nodes.clear()`, but let's be very precise:
cloned_nodes.erase(std::remove_if(
cloned_nodes.begin(), cloned_nodes.end(),
[](my_class const& v) { return !v.is_linked(); }),
cloned_nodes.end());
}
事实上,这是一个将克隆节点放在与源节点相同的向量中的版本,为了好玩: Live On Coliru 。