I have a boost::intrusive::list<Foo, constant_time_size<false>>, where Foo inherits from the list_base_hook<auto_unlink> hook. With a list element foo, I am able to get its iterator by calling list::s_iterator_to(foo). My question is how I can traverse the list with this iterator. In particular, is there a way to tell if this element is the only one in the list?

The source suggests list uses a cicular_list_algorithms in its value traits and perhaps I can use the following test?

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

It looks quite hacky but it seeminly works. I'm not sure if it is correct and idiomatic. Can somebody please advise?

The complete listing:

#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;
}

Yes, I do realize dereferencing ++itr1 and --itr1 is wrong. Is there any way that I can compare the addresses of the underlying nodes directly? I imagine foo has both links to its predecessor and successor and they should be equal to each other if foo is the only element.

1

There are 1 best solutions below

4
hslaster On

I tried these, and it worked. However, it is tightly coupled with the implementation details. The idea is to get the underlying node pointer from the value and compare the pointers.

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;