1 /* Copyright 2003-2019 Joaquin M Lopez Munoz. 2 * Distributed under the Boost Software License, Version 1.0. 3 * (See accompanying file LICENSE_1_0.txt or copy at 4 * http://www.boost.org/LICENSE_1_0.txt) 5 * 6 * See http://www.boost.org/libs/multi_index for library home page. 7 */ 8 9 #ifndef BOOST_MULTI_INDEX_KEY_HPP 10 #define BOOST_MULTI_INDEX_KEY_HPP 11 12 #if defined(_MSC_VER) 13 #pragma once 14 #endif 15 16 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ 17 #include <boost/multi_index/composite_key.hpp> 18 #include <boost/multi_index/global_fun.hpp> 19 #include <boost/multi_index/member.hpp> 20 #include <boost/multi_index/mem_fun.hpp> 21 22 #if __cplusplus>=201703L||\ 23 defined(BOOST_MSVC)&&defined(__cpp_nontype_template_parameter_auto) 24 25 #define BOOST_MULTI_INDEX_KEY_SUPPORTED 26 27 #include <boost/multi_index/detail/is_function.hpp> 28 #include <boost/preprocessor/facilities/empty.hpp> 29 #include <type_traits> 30 31 namespace boost{ 32 33 namespace multi_index{ 34 35 /* C++17 terse key specification syntax */ 36 37 namespace detail{ 38 39 template<typename T,T,typename=void> 40 struct typed_key_impl; 41 42 template<typename Class,typename Type,Type Class::*PtrToMember> 43 struct typed_key_impl< 44 Type Class::*,PtrToMember, 45 typename std::enable_if<!is_function<Type>::value>::type 46 > 47 { 48 using value_type=Class; 49 using type=member<Class,Type,PtrToMember>; 50 }; 51 52 #define BOOST_MULTI_INDEX_KEY_TYPED_KEY_IMPL(qualifier,extractor) \ 53 template< \ 54 typename Class,typename Type,Type (Class::*PtrToMemberFunction)()qualifier \ 55 > \ 56 struct typed_key_impl<Type (Class::*)()qualifier,PtrToMemberFunction> \ 57 { \ 58 using value_type=Class; \ 59 using type=extractor<Class,Type,PtrToMemberFunction>; \ 60 }; 61 62 BOOST_MULTI_INDEX_KEY_TYPED_KEY_IMPL( ,mem_fun) 63 BOOST_MULTI_INDEX_KEY_TYPED_KEY_IMPL(const ,const_mem_fun) 64 BOOST_MULTI_INDEX_KEY_TYPED_KEY_IMPL(volatile ,volatile_mem_fun) 65 BOOST_MULTI_INDEX_KEY_TYPED_KEY_IMPL(const volatile ,cv_mem_fun) 66 BOOST_MULTI_INDEX_KEY_TYPED_KEY_IMPL(& ,ref_mem_fun) 67 BOOST_MULTI_INDEX_KEY_TYPED_KEY_IMPL(const& ,cref_mem_fun) 68 BOOST_MULTI_INDEX_KEY_TYPED_KEY_IMPL(volatile& ,vref_mem_fun) 69 BOOST_MULTI_INDEX_KEY_TYPED_KEY_IMPL(const volatile& ,cvref_mem_fun) 70 71 #undef BOOST_MULTI_INDEX_KEY_TYPED_KEY_IMPL 72 73 template<class Value,typename Type,Type (*PtrToFunction)(Value)> 74 struct typed_key_impl<Type (*)(Value),PtrToFunction> 75 { 76 using value_type=Value; 77 using type=global_fun<Value,Type,PtrToFunction>; 78 }; 79 80 template<typename T> 81 struct remove_noexcept{using type=T;}; 82 83 #define BOOST_MULTI_INDEX_KEY_REMOVE_MEMFUN_NOEXCEPT(qualifier) \ 84 template<typename R,typename C,typename... Args> \ 85 struct remove_noexcept<R(C::*)(Args...)qualifier noexcept> \ 86 {using type=R(C::*)(Args...)qualifier;}; \ 87 \ 88 template<typename R,typename C,typename... Args> \ 89 struct remove_noexcept<R(C::*)(Args...,...)qualifier noexcept> \ 90 {using type=R(C::*)(Args...,...)qualifier;}; 91 92 BOOST_MULTI_INDEX_KEY_REMOVE_MEMFUN_NOEXCEPT(BOOST_PP_EMPTY()) 93 /* VS warns without dummy arg */ 94 BOOST_MULTI_INDEX_KEY_REMOVE_MEMFUN_NOEXCEPT(const) 95 BOOST_MULTI_INDEX_KEY_REMOVE_MEMFUN_NOEXCEPT(volatile) 96 BOOST_MULTI_INDEX_KEY_REMOVE_MEMFUN_NOEXCEPT(const volatile) 97 BOOST_MULTI_INDEX_KEY_REMOVE_MEMFUN_NOEXCEPT(&) 98 BOOST_MULTI_INDEX_KEY_REMOVE_MEMFUN_NOEXCEPT(const&) 99 BOOST_MULTI_INDEX_KEY_REMOVE_MEMFUN_NOEXCEPT(volatile&) 100 BOOST_MULTI_INDEX_KEY_REMOVE_MEMFUN_NOEXCEPT(const volatile&) 101 BOOST_MULTI_INDEX_KEY_REMOVE_MEMFUN_NOEXCEPT(&&) 102 BOOST_MULTI_INDEX_KEY_REMOVE_MEMFUN_NOEXCEPT(const&&) 103 BOOST_MULTI_INDEX_KEY_REMOVE_MEMFUN_NOEXCEPT(volatile&&) 104 BOOST_MULTI_INDEX_KEY_REMOVE_MEMFUN_NOEXCEPT(const volatile&&) 105 106 #undef BOOST_MULTI_INDEX_KEY_REMOVE_MEMFUN_NOEXCEPT 107 108 template<typename R,typename... Args> 109 struct remove_noexcept<R(*)(Args...)noexcept>{using type=R(*)(Args...);}; 110 template<typename R,typename... Args> 111 struct remove_noexcept<R(*)(Args...,...)noexcept> 112 {using type=R(*)(Args...,...);}; 113 114 template<typename T> 115 using remove_noexcept_t=typename remove_noexcept<T>::type; 116 117 template<auto... Keys> 118 struct key_impl; 119 120 template<auto Key> 121 struct key_impl<Key>:typed_key_impl<remove_noexcept_t<decltype(Key)>,Key>{}; 122 123 template<typename... Ts> 124 struct least_generic; 125 126 template<typename T0,typename... Ts> 127 struct least_generic<T0,Ts...> 128 { 129 using type=T0; 130 }; 131 132 template<typename T0,typename T1,typename... Ts> 133 struct least_generic<T0,T1,Ts...> 134 { 135 static_assert( 136 std::is_convertible<const T0&,const T1&>::value|| 137 std::is_convertible<const T1&,const T0&>::value, 138 "one type should be convertible to the other"); 139 140 using type=typename least_generic< 141 typename std::conditional< 142 std::is_convertible<const T0&,const T1&>::value,T0,T1 143 >::type, 144 Ts... 145 >::type; 146 }; 147 148 template<auto Key0,auto... Keys> 149 struct key_impl<Key0,Keys...> 150 { 151 using value_type=typename least_generic< 152 typename std::decay<typename key_impl<Key0>::value_type>::type, 153 typename std::decay<typename key_impl<Keys>::value_type>::type... 154 >::type; 155 using type=composite_key< 156 value_type, 157 typename key_impl<Key0>::type, 158 typename key_impl<Keys>::type... 159 >; 160 }; 161 162 template<typename=composite_key<void,void>> 163 struct composite_key_size; 164 165 template<typename... Args> 166 struct composite_key_size<composite_key<Args...>> 167 { 168 static constexpr auto value=sizeof...(Args)-1; 169 }; 170 171 template<auto... Keys> 172 struct limited_size_key_impl 173 { 174 static_assert( 175 sizeof...(Keys)<=composite_key_size<>::value, 176 "specified number of keys must meet the limits of " 177 "boost::multi_index::composite_key"); 178 using type=typename key_impl<Keys...>::type; 179 }; 180 181 } /* namespace multi_index::detail */ 182 183 template<auto... Keys> 184 using key=typename detail::limited_size_key_impl<Keys...>::type; 185 186 } /* namespace multi_index */ 187 188 } /* namespace boost */ 189 190 #endif 191 #endif 192