stateful_value_traits_test.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2007-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. #include <boost/intrusive/list.hpp>
  13. #include <boost/intrusive/slist.hpp>
  14. #include <boost/intrusive/set.hpp>
  15. #include <boost/intrusive/unordered_set.hpp>
  16. #include <boost/functional/hash.hpp>
  17. #include <boost/intrusive/pointer_traits.hpp>
  18. #include <vector>
  19. using namespace boost::intrusive;
  20. class MyClass
  21. {
  22. public:
  23. int int_;
  24. MyClass(int i = 0)
  25. : int_(i)
  26. {}
  27. friend bool operator<(const MyClass &l, const MyClass &r)
  28. { return l.int_ < r.int_; }
  29. friend bool operator==(const MyClass &l, const MyClass &r)
  30. { return l.int_ == r.int_; }
  31. friend std::size_t hash_value(const MyClass &v)
  32. { return boost::hash_value(v.int_); }
  33. };
  34. template<class T, class NodeTraits>
  35. struct stateful_value_traits
  36. {
  37. typedef NodeTraits node_traits;
  38. typedef typename node_traits::node node;
  39. typedef typename node_traits::node_ptr node_ptr;
  40. typedef typename node_traits::const_node_ptr const_node_ptr;
  41. typedef T value_type;
  42. typedef typename pointer_traits<node_ptr>::
  43. template rebind_pointer<T>::type pointer;
  44. typedef typename pointer_traits<node_ptr>::
  45. template rebind_pointer<const T>::type const_pointer;
  46. static const link_mode_type link_mode = normal_link;
  47. stateful_value_traits(pointer vals, node_ptr node_array)
  48. : values_(vals), node_array_(node_array)
  49. {}
  50. node_ptr to_node_ptr (value_type &value) const
  51. { return node_array_ + (&value - values_); }
  52. const_node_ptr to_node_ptr (const value_type &value) const
  53. { return node_array_ + (&value - values_); }
  54. pointer to_value_ptr(const node_ptr &n) const
  55. { return values_ + (n - node_array_); }
  56. const_pointer to_value_ptr(const const_node_ptr &n) const
  57. { return values_ + (n - node_array_); }
  58. pointer values_;
  59. node_ptr node_array_;
  60. };
  61. //Define a list that will store MyClass using the external hook
  62. typedef stateful_value_traits< MyClass, list_node_traits<void*> > list_traits;
  63. typedef list<MyClass, value_traits<list_traits> > List;
  64. //Define a slist that will store MyClass using the external hook
  65. typedef stateful_value_traits< MyClass, slist_node_traits<void*> > slist_traits;
  66. typedef slist<MyClass, value_traits<slist_traits> > Slist;
  67. //Define a set that will store MyClass using the external hook
  68. typedef stateful_value_traits< MyClass, rbtree_node_traits<void*> > rbtree_traits;
  69. typedef set<MyClass, value_traits<rbtree_traits> > Set;
  70. //uset uses the same traits as slist
  71. typedef unordered_set<MyClass, value_traits<slist_traits> > Uset;
  72. typedef list_traits::node list_node_t;
  73. typedef slist_traits::node slist_node_t;
  74. typedef rbtree_traits::node rbtree_node_t;
  75. const int NumElements = 100;
  76. MyClass values [NumElements];
  77. list_node_t list_hook_array [NumElements];
  78. slist_node_t slist_hook_array [NumElements];
  79. rbtree_node_t rbtree_hook_array [NumElements];
  80. slist_node_t uset_hook_array [NumElements];
  81. int main()
  82. {
  83. //Create several MyClass objects, each one with a different value
  84. for(int i = 0; i < NumElements; ++i)
  85. values[i].int_ = i;
  86. Uset::bucket_type buckets[NumElements];
  87. List my_list (list_traits (values, list_hook_array));
  88. Slist my_slist(slist_traits(values, slist_hook_array));
  89. Set my_set (std::less<MyClass>(), rbtree_traits(values, rbtree_hook_array));
  90. Uset my_uset ( Uset::bucket_traits(buckets, NumElements)
  91. , boost::hash<MyClass>()
  92. , std::equal_to<MyClass>()
  93. , slist_traits(values, uset_hook_array)
  94. );
  95. //Now insert them in containers
  96. for(MyClass * it(&values[0]), *itend(&values[NumElements])
  97. ; it != itend
  98. ; ++it){
  99. my_list.push_front(*it);
  100. if(&*my_list.iterator_to(*it) != &my_list.front())
  101. return 1;
  102. my_slist.push_front(*it);
  103. if(&*my_slist.iterator_to(*it) != &my_slist.front())
  104. return 1;
  105. Set::iterator sit = my_set.insert(*it).first;
  106. if(&*my_set.iterator_to(*it) != &*sit)
  107. return 1;
  108. Uset::iterator uit = my_uset.insert(*it).first;
  109. my_uset.insert(*it);
  110. if(&*my_uset.iterator_to(*it) != &*uit)
  111. return 1;
  112. }
  113. //Now test lists
  114. {
  115. List::const_iterator list_it (my_list.cbegin());
  116. Slist::const_iterator slist_it(my_slist.cbegin());
  117. Set::const_reverse_iterator set_rit(my_set.crbegin());
  118. MyClass *it_val(&values[NumElements]), *it_rbeg_val(&values[0]);
  119. //Test the objects inserted in the base hook list
  120. for(; it_val != it_rbeg_val; --it_val, ++list_it, ++slist_it, ++set_rit){
  121. if(&*list_it != &it_val[-1]) return 1;
  122. if(&*slist_it != &it_val[-1]) return 1;
  123. if(&*set_rit != &it_val[-1]) return 1;
  124. if(my_uset.find(it_val[-1]) == my_uset.cend()) return 1;
  125. }
  126. }
  127. return 0;
  128. }