1 /////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Olaf Krzikalla 2004-2006.
4 // (C) Copyright Ion Gaztanaga  2006-2013.
5 //
6 // Distributed under the Boost Software License, Version 1.0.
7 //    (See accompanying file LICENSE_1_0.txt or copy at
8 //          http://www.boost.org/LICENSE_1_0.txt)
9 //
10 // See http://www.boost.org/libs/intrusive for documentation.
11 //
12 /////////////////////////////////////////////////////////////////////////////
13 #ifndef BOOST_INTRUSIVE_DETAIL_ITESTVALUE_HPP
14 #define BOOST_INTRUSIVE_DETAIL_ITESTVALUE_HPP
15 
16 #include <iostream>
17 #include <boost/intrusive/options.hpp>
18 #include <boost/functional/hash.hpp>
19 #include <boost/intrusive/pointer_traits.hpp>
20 #include "nonhook_node.hpp"
21 #include "int_holder.hpp"
22 #include <boost/intrusive/detail/get_value_traits.hpp>
23 #include <boost/container/vector.hpp>
24 
25 namespace boost{
26 namespace intrusive{
27 
28 struct testvalue_filler
29 {
30    void *dummy_[3];
31 };
32 
33 template<class Hooks>
34 struct testvalue
35    :  testvalue_filler
36    ,  Hooks::base_hook_type
37    ,  Hooks::auto_base_hook_type
38 {
39    typename Hooks::member_hook_type        node_;
40    typename Hooks::auto_member_hook_type   auto_node_;
41    typename Hooks::nonhook_node_member_type nhn_member_;
42 
43    int_holder value_;
44 
testvalueboost::intrusive::testvalue45    testvalue()
46    {}
47 
testvalueboost::intrusive::testvalue48    explicit testvalue(int i)
49       :  value_(i)
50    {}
51 
testvalueboost::intrusive::testvalue52    testvalue (const testvalue& src)
53       :  value_(src.value_)
54    {}
55 
56    // testvalue is used in boost::container::vector and thus prev and next
57    // have to be handled appropriately when copied:
operator =boost::intrusive::testvalue58    testvalue & operator= (const testvalue& src)
59    {
60       Hooks::base_hook_type::operator=(static_cast<const typename Hooks::base_hook_type&>(src));
61       Hooks::auto_base_hook_type::operator=(static_cast<const typename Hooks::auto_base_hook_type&>(src));
62       this->node_       = src.node_;
63       this->auto_node_  = src.auto_node_;
64       this->nhn_member_ = src.nhn_member_;
65       value_ = src.value_;
66       return *this;
67    }
68 
swap_nodesboost::intrusive::testvalue69    void swap_nodes(testvalue &other)
70    {
71       Hooks::base_hook_type::swap_nodes(static_cast<typename Hooks::base_hook_type&>(other));
72       Hooks::auto_base_hook_type::swap_nodes(static_cast<typename Hooks::auto_base_hook_type&>(other));
73       node_.swap_nodes(other.node_);
74       auto_node_.swap_nodes(other.auto_node_);
75       nhn_member_.swap_nodes(other.nhn_member_);
76    }
77 
is_linkedboost::intrusive::testvalue78    bool is_linked() const
79    {
80       return Hooks::base_hook_type::is_linked() ||
81       Hooks::auto_base_hook_type::is_linked() ||
82       node_.is_linked() ||
83       auto_node_.is_linked() ||
84       nhn_member_.is_linked();
85    }
86 
get_int_holderboost::intrusive::testvalue87    const int_holder &get_int_holder() const
88    {  return value_; }
89 
int_valueboost::intrusive::testvalue90    int int_value() const
91    {  return value_.int_value();  }
92 
~testvalueboost::intrusive::testvalue93    ~testvalue()
94    {}
95 
operator <boost::intrusive::testvalue96    bool operator< (const testvalue &other) const
97    {  return value_ < other.value_;  }
98 
operator >boost::intrusive::testvalue99    bool operator> (const testvalue &other) const
100    {  return value_ > other.value_;  }
101 
operator ==boost::intrusive::testvalue102    bool operator==(const testvalue &other) const
103    {  return value_ == other.value_;  }
104 
operator !=boost::intrusive::testvalue105    bool operator!=(const testvalue &other) const
106    {  return value_ != other.value_;  }
107 
operator <(int other1,const testvalue & other2)108    friend bool operator< (int other1, const testvalue &other2)
109    {  return other1 < other2.value_.int_;  }
110 
operator >(int other1,const testvalue & other2)111    friend bool operator> (int other1, const testvalue &other2)
112    {  return other1 > other2.value_.int_;  }
113 
operator <(const testvalue & other1,int other2)114    friend bool operator< (const testvalue &other1, int other2)
115    {  return other1.value_.int_ < other2;  }
116 
operator >(const testvalue & other1,int other2)117    friend bool operator> (const testvalue &other1, int other2)
118    {  return other1.value_.int_ > other2;  }
119 
operator ==(int other1,const testvalue & other2)120    friend bool operator== (int other1, const testvalue &other2)
121    {  return other1 == other2.value_.int_;  }
122 
operator ==(const testvalue & other1,int other2)123    friend bool operator== (const testvalue &other1, int other2)
124    {  return other1.value_.int_ == other2;  }
125 
operator !=(int other1,const testvalue & other2)126    friend bool operator!= (int other1, const testvalue &other2)
127    {  return other1 != other2.value_.int_;  }
128 
operator !=(const testvalue & other1,int other2)129    friend bool operator!= (const testvalue &other1, int other2)
130    {  return other1.value_.int_ != other2;  }
131 
hash_value(const testvalue & t)132    friend std::size_t hash_value(const testvalue&t)
133    {
134       boost::hash<int> hasher;
135       return hasher((&t)->int_value());
136    }
137 };
138 
139 template<class T>
priority_hash(const T & t)140 std::size_t priority_hash(const T &t)
141 {  return boost::hash<int>()((&t)->int_value()); }
142 
priority_hash(int i)143 std::size_t priority_hash(int i)
144 {  return boost::hash<int>()(i); }
145 
146 template <class T, class U>
priority_order(const T & t1,const U & t2)147 bool priority_order(const T& t1, const U& t2)
148 {
149    std::size_t hash1 = (priority_hash)(t1);
150    boost::hash_combine(hash1, -hash1);
151    std::size_t hash2 = (priority_hash)(t2);
152    boost::hash_combine(hash2, -hash2);
153    return hash1 < hash2;
154 }
155 
156 template < typename Node_Algorithms, class Hooks>
swap_nodes(testvalue<Hooks> & lhs,testvalue<Hooks> & rhs)157 void swap_nodes(testvalue<Hooks>& lhs, testvalue<Hooks>& rhs)
158 {
159     lhs.swap_nodes(rhs);
160 }
161 
162 template<class Hooks>
operator <<(std::ostream & s,const testvalue<Hooks> & t)163 std::ostream& operator<<
164    (std::ostream& s, const testvalue<Hooks>& t)
165 {  return s << t.value_.int_value();   }
166 
167 struct even_odd
168 {
169    template < typename key_type_1, typename key_type_2 >
operator ()boost::intrusive::even_odd170    bool operator()
171       (const key_type_1& v1
172       ,const key_type_2& v2) const
173    {
174       if (((&v1)->int_value() & 1) == ((&v2)->int_value() & 1))
175          return (&v1)->int_value() < (&v2)->int_value();
176       else
177          return (&v2)->int_value() & 1;
178    }
179 };
180 
181 struct is_even
182 {
183    template <typename key_type>
operator ()boost::intrusive::is_even184    bool operator()
185       (const key_type& v1) const
186    {  return ((&v1)->int_value() & 1) == 0;  }
187 };
188 
189 struct is_odd
190 {
191    template <typename key_type>
operator ()boost::intrusive::is_odd192    bool operator()
193       (const key_type& v1) const
194    {  return ((&v1)->int_value() & 1) != 0;  }
195 };
196 
197 template <typename>
198 struct ValueContainer;
199 
200 template < class Hooks>
201 struct ValueContainer< testvalue<Hooks> >
202 {
203     typedef boost::container::vector< testvalue<Hooks> > type;
204 };
205 
206 template < typename Pointer >
207 class heap_node_holder
208 {
209    typedef typename pointer_traits<Pointer>::element_type element_type;
210    typedef Pointer pointer;
211    typedef typename pointer_rebind<pointer, const element_type>::type const_pointer;
212 
213    public:
heap_node_holder()214    heap_node_holder()
215       : m_ptr(pointer_traits<Pointer>::pointer_to(*new element_type))
216    {}
217 
~heap_node_holder()218    ~heap_node_holder()
219    { delete &*m_ptr;   }
220 
get_node() const221    const_pointer get_node() const
222    { return m_ptr; }
223 
get_node()224    pointer get_node()
225    { return m_ptr; }
226 
227    private:
228    pointer m_ptr;
229 };
230 
231 template<class Hooks>
232 struct testvalue_traits
233    : public Hooks
234 {
235    typedef testvalue< Hooks > value_type;
236 
237    //base
238    typedef typename detail::get_base_value_traits
239          < value_type
240          , typename Hooks::base_hook_type
241          >::type base_value_traits;
242    //auto-base
243    typedef typename detail::get_base_value_traits
244          < value_type
245          , typename Hooks::auto_base_hook_type
246          >::type auto_base_value_traits;
247    //member
248    typedef typename detail::get_member_value_traits
249          < member_hook
250             < value_type
251             , typename Hooks::member_hook_type
252             , &value_type::node_
253             >
254          >::type member_value_traits;
255    //auto-member
256    typedef typename detail::get_member_value_traits
257          < member_hook
258             < value_type
259             , typename Hooks::auto_member_hook_type
260             , &value_type::auto_node_
261             >
262          >::type auto_member_value_traits;
263    //nonmember
264    typedef nonhook_node_member_value_traits
265          < value_type
266          , typename Hooks::nonhook_node_member_type
267          , &value_type::nhn_member_
268          , safe_link
269          > nonhook_value_traits;
270 };
271 
272 }  //namespace intrusive{
273 }  //namespace boost{
274 
priority_order(int t1,int t2)275 bool priority_order(int t1, int t2)
276 {
277    std::size_t hash1 = boost::hash<int>()(t1);
278    boost::hash_combine(hash1, &t1);
279    std::size_t hash2 = boost::hash<int>()(t2);
280    boost::hash_combine(hash2, &t2);
281    return hash1 < hash2;
282 }
283 
284 #endif
285