1 /////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga  2014-2014
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 
13 #ifndef BOOST_INTRUSIVE_DETAIL_KEY_NODEPTR_COMP_HPP
14 #define BOOST_INTRUSIVE_DETAIL_KEY_NODEPTR_COMP_HPP
15 
16 #ifndef BOOST_CONFIG_HPP
17 #  include <boost/config.hpp>
18 #endif
19 
20 #if defined(BOOST_HAS_PRAGMA_ONCE)
21 #  pragma once
22 #endif
23 
24 #include <boost/intrusive/detail/mpl.hpp>
25 #include <boost/intrusive/detail/ebo_functor_holder.hpp>
26 #include <boost/intrusive/detail/tree_value_compare.hpp>
27 
28 
29 namespace boost {
30 namespace intrusive {
31 namespace detail {
32 
33 template < class KeyTypeKeyCompare
34          , class ValueTraits
35          , class KeyOfValue
36          >
37 struct key_nodeptr_comp_types
38 {
39    typedef ValueTraits                                   value_traits;
40    typedef typename value_traits::value_type             value_type;
41    typedef typename value_traits::node_ptr               node_ptr;
42    typedef typename value_traits::const_node_ptr         const_node_ptr;
43    typedef typename detail::if_c
44             < detail::is_same<KeyOfValue, void>::value
45             , detail::identity<value_type>
46             , KeyOfValue
47             >::type                                      key_of_value;
48    typedef tree_value_compare
49       <typename ValueTraits::pointer, KeyTypeKeyCompare, key_of_value>      base_t;
50 };
51 
52 //This function object transforms a key comparison type to
53 //a function that can compare nodes or nodes with nodes or keys.
54 template < class KeyTypeKeyCompare
55          , class ValueTraits
56          , class KeyOfValue = void
57          >
58 struct key_nodeptr_comp
59    //Use public inheritance to avoid MSVC bugs with closures
60    :  public key_nodeptr_comp_types<KeyTypeKeyCompare, ValueTraits, KeyOfValue>::base_t
61 {
62 private:
63    struct sfinae_type;
64 
65 public:
66    typedef key_nodeptr_comp_types<KeyTypeKeyCompare, ValueTraits, KeyOfValue> types_t;
67    typedef typename types_t::value_traits          value_traits;
68    typedef typename types_t::value_type            value_type;
69    typedef typename types_t::node_ptr              node_ptr;
70    typedef typename types_t::const_node_ptr        const_node_ptr;
71    typedef typename types_t::base_t                base_t;
72    typedef typename types_t::key_of_value          key_of_value;
73 
74    template <class P1>
75    struct is_same_or_nodeptr_convertible
76    {
77       static const bool same_type = is_same<P1,const_node_ptr>::value || is_same<P1,node_ptr>::value;
78       static const bool value = same_type || is_convertible<P1, const_node_ptr>::value;
79    };
80 
baseboost::intrusive::detail::key_nodeptr_comp81    BOOST_INTRUSIVE_FORCEINLINE base_t base() const
82    {  return static_cast<const base_t&>(*this); }
83 
key_nodeptr_compboost::intrusive::detail::key_nodeptr_comp84    BOOST_INTRUSIVE_FORCEINLINE key_nodeptr_comp(KeyTypeKeyCompare kcomp, const ValueTraits *traits)
85       :  base_t(kcomp), traits_(traits)
86    {}
87 
88    //pred(pnode)
89    template<class T1>
operator ()boost::intrusive::detail::key_nodeptr_comp90    BOOST_INTRUSIVE_FORCEINLINE bool operator()(const T1 &t1, typename enable_if_c< is_same_or_nodeptr_convertible<T1>::value, sfinae_type* >::type = 0) const
91    {  return base().get()(key_of_value()(*traits_->to_value_ptr(t1)));  }
92 
93    //operator() 2 arg
94    //pred(pnode, pnode)
95    template<class T1, class T2>
operator ()boost::intrusive::detail::key_nodeptr_comp96    BOOST_INTRUSIVE_FORCEINLINE bool operator()
97       (const T1 &t1, const T2 &t2, typename enable_if_c< is_same_or_nodeptr_convertible<T1>::value && is_same_or_nodeptr_convertible<T2>::value, sfinae_type* >::type = 0) const
98    {  return base()(*traits_->to_value_ptr(t1), *traits_->to_value_ptr(t2));  }
99 
100    //pred(pnode, key)
101    template<class T1, class T2>
operator ()boost::intrusive::detail::key_nodeptr_comp102    BOOST_INTRUSIVE_FORCEINLINE bool operator()
103       (const T1 &t1, const T2 &t2, typename enable_if_c< is_same_or_nodeptr_convertible<T1>::value && !is_same_or_nodeptr_convertible<T2>::value, sfinae_type* >::type = 0) const
104    {  return base()(*traits_->to_value_ptr(t1), t2);  }
105 
106    //pred(key, pnode)
107    template<class T1, class T2>
operator ()boost::intrusive::detail::key_nodeptr_comp108    BOOST_INTRUSIVE_FORCEINLINE bool operator()
109       (const T1 &t1, const T2 &t2, typename enable_if_c< !is_same_or_nodeptr_convertible<T1>::value && is_same_or_nodeptr_convertible<T2>::value, sfinae_type* >::type = 0) const
110    {  return base()(t1, *traits_->to_value_ptr(t2));  }
111 
112    //pred(key, key)
113    template<class T1, class T2>
operator ()boost::intrusive::detail::key_nodeptr_comp114    BOOST_INTRUSIVE_FORCEINLINE bool operator()
115       (const T1 &t1, const T2 &t2, typename enable_if_c< !is_same_or_nodeptr_convertible<T1>::value && !is_same_or_nodeptr_convertible<T2>::value, sfinae_type* >::type = 0) const
116    {  return base()(t1, t2);  }
117 
118    const ValueTraits *const traits_;
119 };
120 
121 }  //namespace detail{
122 }  //namespace intrusive{
123 }  //namespace boost{
124 
125 #endif //BOOST_INTRUSIVE_DETAIL_KEY_NODEPTR_COMP_HPP
126