boost::instrusive::list 带有自动取消链接钩子:我可以使用列表中的值来确定列表是否只有一个元素

boost::instrusive::list with the auto-unlink hook: can I use a value in the list to determine if the list has exactly one element?

本文关键字:列表 元素 有一个 是否 我可以 list instrusive 取消 boost 链接 可以使      更新时间:2023-10-16

我有一个boost::intrusive::list<Foo, constant_time_size<false>>,其中Foo继承自list_base_hook<auto_unlink>钩子。使用列表元素foo,我可以通过调用list::s_iterator_to(foo)来获取它的迭代器。我的问题是如何使用此迭代器遍历列表。特别是,有没有办法判断这个元素是否是列表中唯一的元素?

消息来源建议list在其价值特征中使用cicular_list_algorithms,也许我可以使用以下测试?

auto itr1 = list_t::s_iterator_to(foo);
auto itr2 = list_t::s_iterator_to(foo);
&(*++itr1) == &(*--itr2);

它看起来很笨拙,但它似乎有效。我不确定它是否正确和惯用。有人可以建议吗?

完整列表:

#include <iostream>
#include <boost/intrusive/list.hpp>
using namespace boost::intrusive;
typedef list_base_hook<link_mode<auto_unlink> > auto_unlink_hook;
class Foo : public auto_unlink_hook
{
    int int_;
    public:
    Foo(int i = 0)   :  int_(i)  {}
    int  get_int()    { return int_; }
    void unlink()     {  auto_unlink_hook::unlink(); }
    bool is_linked()  {  return auto_unlink_hook::is_linked();  }
};
int main()
{
    typedef list<Foo, constant_time_size<false>> ListType;
    ListType l;
    Foo foo1{42};
    l.push_back(foo1);
    auto itr1 = ListType::s_iterator_to(foo1);
    auto itr2 = ListType::s_iterator_to(foo1);
    std::cout << (&(*++itr1) == &(*--itr2)) << std::endl;
    Foo foo2{43};
    l.push_back(foo2);
    itr1 = ListType::s_iterator_to(foo1);
    itr2 = ListType::s_iterator_to(foo1);
    std::cout << (&(*++itr1) == &(*--itr2)) << std::endl;
    foo1.unlink();
    return 0;
}

是的,我确实意识到取消引用++itr1--itr1是错误的。有什么方法可以直接比较底层节点的地址吗?我想foo与其前身和继任者都有联系,如果foo是唯一的元素,它们应该彼此平等。

我尝试了这些,它奏效了。但是,它与实现细节紧密结合。这个想法是从值中获取基础节点指针并比较指针。

typedef list<Foo, constant_time_size<false>> ListType;                                    
ListType l;                                                                               
Foo foo1{42};                                                                             
l.push_back(foo1);                                                                        
ListType::const_node_ptr cur = ListType::value_traits::to_node_ptr(foo1);                 
std::cout << (ListType::node_traits::get_previous(cur) == ListType::node_traits::get_next(cur)) << std::endl;
Foo foo2{43};                                                                             
l.push_back(foo2);                                                                        
std::cout << (ListType::node_traits::get_previous(cur) == ListType::node_traits::get_next(cur)) << std::endl;