1 /////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga  2006-2013
4 //
5 // Distributed under the Boost Software License, Version 1.0.
6 //    (See accompanying file LICENSE_1_0.txt or copy at
7 //          http://www.boost.org/LICENSE_1_0.txt)
8 //
9 // See http://www.boost.org/libs/intrusive for documentation.
10 //
11 /////////////////////////////////////////////////////////////////////////////
12 //[doc_advanced_value_traits_code
13 #include <boost/intrusive/link_mode.hpp>
14 #include <boost/intrusive/list.hpp>
15 #include <vector>
16 
17 //This is the node that will be used with algorithms.
18 struct simple_node
19 {
20    simple_node *prev_;
21    simple_node *next_;
22 };
23 //]
24 
25 //[doc_advanced_value_traits_value_traits
26 class base_1{};
27 class base_2{};
28 
29 struct value_1 :  public base_1, public simple_node
30 {  int   id_;  };
31 
32 struct value_2 :  public base_1, public base_2, public simple_node
33 {  float id_;  };
34 
35 //Define the node traits. A single node_traits will be enough.
36 struct simple_node_traits
37 {
38    typedef simple_node                             node;
39    typedef node *                                  node_ptr;
40    typedef const node *                            const_node_ptr;
get_nextsimple_node_traits41    static node *get_next(const node *n)            {  return n->next_;  }
set_nextsimple_node_traits42    static void set_next(node *n, node *next)       {  n->next_ = next;  }
get_previoussimple_node_traits43    static node *get_previous(const node *n)        {  return n->prev_;  }
set_previoussimple_node_traits44    static void set_previous(node *n, node *prev)   {  n->prev_ = prev;  }
45 };
46 
47 //A templatized value traits for value_1 and value_2
48 template<class ValueType>
49 struct simple_value_traits
50 {
51    typedef simple_node_traits                                  node_traits;
52    typedef node_traits::node_ptr                               node_ptr;
53    typedef node_traits::const_node_ptr                         const_node_ptr;
54    typedef ValueType                                           value_type;
55    typedef ValueType *                                         pointer;
56    typedef const ValueType *                                   const_pointer;
57    static const boost::intrusive::link_mode_type link_mode = boost::intrusive::normal_link;
to_node_ptrsimple_value_traits58    static node_ptr to_node_ptr (value_type &value)             {  return node_ptr(&value); }
to_node_ptrsimple_value_traits59    static const_node_ptr to_node_ptr (const value_type &value) {  return const_node_ptr(&value); }
to_value_ptrsimple_value_traits60    static pointer to_value_ptr(node_ptr n)                     {  return static_cast<value_type*>(n); }
to_value_ptrsimple_value_traits61    static const_pointer to_value_ptr(const_node_ptr n)         {  return static_cast<const value_type*>(n); }
62 };
63 //]
64 
65 //[doc_advanced_value_traits_containers
66 //Now define two intrusive lists. Both lists will use the same algorithms:
67 // circular_list_algorithms<simple_node_traits>
68 
69 using namespace boost::intrusive;
70 typedef list <value_1, value_traits<simple_value_traits<value_1> > > Value1List;
71 typedef list <value_2, value_traits<simple_value_traits<value_2> > > Value2List;
72 //]
73 
74 //[doc_advanced_value_traits_test
main()75 int main()
76 {
77    typedef std::vector<value_1> Vect1;
78    typedef std::vector<value_2> Vect2;
79 
80    //Create values, with a different internal number
81    Vect1 values1;
82    Vect2 values2;
83    for(int i = 0; i < 100; ++i){
84       value_1 v1;    v1.id_ = i;          values1.push_back(v1);
85       value_2 v2;    v2.id_ = (float)i;   values2.push_back(v2);
86    }
87 
88    //Create the lists with the objects
89    Value1List list1(values1.begin(), values1.end());
90    Value2List list2(values2.begin(), values2.end());
91 
92    //Now test both lists
93    Value1List::const_iterator bit1(list1.begin()), bitend1(list1.end());
94    Value2List::const_iterator bit2(list2.begin()), bitend2(list2.end());
95 
96    Vect1::const_iterator it1(values1.begin()), itend1(values1.end());
97    Vect2::const_iterator it2(values2.begin()), itend2(values2.end());
98 
99    //Test the objects inserted in our lists
100    for(; it1 != itend1; ++it1, ++bit1,  ++it2, ++bit2){
101       if(&*bit1 != &*it1 || &*bit2 != &*it2) return false;
102    }
103    return 0;
104 }
105 //]
106