1 #ifndef BOOST_LEAF_DETAIL_MP11_HPP_INCLUDED 2 #define BOOST_LEAF_DETAIL_MP11_HPP_INCLUDED 3 4 // Copyright 2015-2017 Peter Dimov. 5 // Copyright 2019 Emil Dotchevski. 6 // 7 // Distributed under the Boost Software License, Version 1.0. 8 // 9 // See accompanying file LICENSE_1_0.txt or copy at 10 // http://www.boost.org/LICENSE_1_0.txt 11 12 #include <type_traits> 13 #include <cstddef> 14 15 namespace boost { namespace leaf { namespace leaf_detail_mp11 { 16 17 // mp_list<T...> 18 template<class... T> struct mp_list 19 { 20 }; 21 22 // mp_identity 23 template<class T> struct mp_identity 24 { 25 using type = T; 26 }; 27 28 // mp_inherit 29 template<class... T> struct mp_inherit: T... {}; 30 31 // mp_if, mp_if_c 32 namespace detail 33 { 34 35 template<bool C, class T, class... E> struct mp_if_c_impl 36 { 37 }; 38 39 template<class T, class... E> struct mp_if_c_impl<true, T, E...> 40 { 41 using type = T; 42 }; 43 44 template<class T, class E> struct mp_if_c_impl<false, T, E> 45 { 46 using type = E; 47 }; 48 49 } // namespace detail 50 51 template<bool C, class T, class... E> using mp_if_c = typename detail::mp_if_c_impl<C, T, E...>::type; 52 template<class C, class T, class... E> using mp_if = typename detail::mp_if_c_impl<static_cast<bool>(C::value), T, E...>::type; 53 54 // mp_bool 55 template<bool B> using mp_bool = std::integral_constant<bool, B>; 56 57 using mp_true = mp_bool<true>; 58 using mp_false = mp_bool<false>; 59 60 // mp_to_bool 61 template<class T> using mp_to_bool = mp_bool<static_cast<bool>( T::value )>; 62 63 // mp_not<T> 64 template<class T> using mp_not = mp_bool< !T::value >; 65 66 // mp_int 67 template<int I> using mp_int = std::integral_constant<int, I>; 68 69 // mp_size_t 70 template<std::size_t N> using mp_size_t = std::integral_constant<std::size_t, N>; 71 72 // mp_set_contains<S, V> 73 namespace detail 74 { 75 76 template<class S, class V> struct mp_set_contains_impl; 77 78 template<template<class...> class L, class... T, class V> struct mp_set_contains_impl<L<T...>, V> 79 { 80 using type = mp_to_bool<std::is_base_of<mp_identity<V>, mp_inherit<mp_identity<T>...> > >; 81 }; 82 83 } // namespace detail 84 85 template<class S, class V> using mp_set_contains = typename detail::mp_set_contains_impl<S, V>::type; 86 87 // mp_set_push_back<S, T...> 88 namespace detail 89 { 90 91 template<class S, class... T> struct mp_set_push_back_impl; 92 93 template<template<class...> class L, class... U> struct mp_set_push_back_impl<L<U...>> 94 { 95 using type = L<U...>; 96 }; 97 98 template<template<class...> class L, class... U, class T1, class... T> struct mp_set_push_back_impl<L<U...>, T1, T...> 99 { 100 using S = mp_if<mp_set_contains<L<U...>, T1>, L<U...>, L<U..., T1>>; 101 using type = typename mp_set_push_back_impl<S, T...>::type; 102 }; 103 104 } // namespace detail 105 106 template<class S, class... T> using mp_set_push_back = typename detail::mp_set_push_back_impl<S, T...>::type; 107 108 // mp_unique<L> 109 namespace detail 110 { 111 112 template<class L> struct mp_unique_impl; 113 114 template<template<class...> class L, class... T> struct mp_unique_impl<L<T...>> 115 { 116 using type = mp_set_push_back<L<>, T...>; 117 }; 118 119 } // namespace detail 120 121 template<class L> using mp_unique = typename detail::mp_unique_impl<L>::type; 122 123 // mp_append<L...> 124 125 namespace detail 126 { 127 128 template<class... L> struct mp_append_impl; 129 130 template<> struct mp_append_impl<> 131 { 132 using type = mp_list<>; 133 }; 134 135 template<template<class...> class L, class... T> struct mp_append_impl<L<T...>> 136 { 137 using type = L<T...>; 138 }; 139 140 template<template<class...> class L1, class... T1, template<class...> class L2, class... T2, class... Lr> struct mp_append_impl<L1<T1...>, L2<T2...>, Lr...> 141 { 142 using type = typename mp_append_impl<L1<T1..., T2...>, Lr...>::type; 143 }; 144 145 } 146 147 template<class... L> using mp_append = typename detail::mp_append_impl<L...>::type; 148 149 // mp_front<L> 150 namespace detail 151 { 152 153 template<class L> struct mp_front_impl 154 { 155 // An error "no type named 'type'" here means that the argument to mp_front 156 // is either not a list, or is an empty list 157 }; 158 159 template<template<class...> class L, class T1, class... T> struct mp_front_impl<L<T1, T...>> 160 { 161 using type = T1; 162 }; 163 164 } // namespace detail 165 166 template<class L> using mp_front = typename detail::mp_front_impl<L>::type; 167 168 // mp_pop_front<L> 169 namespace detail 170 { 171 172 template<class L> struct mp_pop_front_impl 173 { 174 // An error "no type named 'type'" here means that the argument to mp_pop_front 175 // is either not a list, or is an empty list 176 }; 177 178 template<template<class...> class L, class T1, class... T> struct mp_pop_front_impl<L<T1, T...>> 179 { 180 using type = L<T...>; 181 }; 182 183 } // namespace detail 184 185 template<class L> using mp_pop_front = typename detail::mp_pop_front_impl<L>::type; 186 187 // mp_first<L> 188 template<class L> using mp_first = mp_front<L>; 189 190 // mp_rest<L> 191 template<class L> using mp_rest = mp_pop_front<L>; 192 193 // mp_remove_if<L, P> 194 namespace detail 195 { 196 197 template<class L, template<class...> class P> struct mp_remove_if_impl; 198 199 template<template<class...> class L, class... T, template<class...> class P> struct mp_remove_if_impl<L<T...>, P> 200 { 201 template<class U> using _f = mp_if<P<U>, mp_list<>, mp_list<U>>; 202 using type = mp_append<L<>, _f<T>...>; 203 }; 204 205 } // namespace detail 206 207 template<class L, template<class...> class P> using mp_remove_if = typename detail::mp_remove_if_impl<L, P>::type; 208 209 // integer_sequence 210 template<class T, T... I> struct integer_sequence 211 { 212 }; 213 214 // detail::make_integer_sequence_impl 215 namespace detail 216 { 217 218 // iseq_if_c 219 template<bool C, class T, class E> struct iseq_if_c_impl; 220 221 template<class T, class E> struct iseq_if_c_impl<true, T, E> 222 { 223 using type = T; 224 }; 225 226 template<class T, class E> struct iseq_if_c_impl<false, T, E> 227 { 228 using type = E; 229 }; 230 231 template<bool C, class T, class E> using iseq_if_c = typename iseq_if_c_impl<C, T, E>::type; 232 233 // iseq_identity 234 template<class T> struct iseq_identity 235 { 236 using type = T; 237 }; 238 239 template<class S1, class S2> struct append_integer_sequence; 240 241 template<class T, T... I, T... J> struct append_integer_sequence<integer_sequence<T, I...>, integer_sequence<T, J...>> 242 { 243 using type = integer_sequence< T, I..., ( J + sizeof...(I) )... >; 244 }; 245 246 template<class T, T N> struct make_integer_sequence_impl; 247 248 template<class T, T N> struct make_integer_sequence_impl_ 249 { 250 private: 251 252 static_assert( N >= 0, "make_integer_sequence<T, N>: N must not be negative" ); 253 254 static T const M = N / 2; 255 static T const R = N % 2; 256 257 using S1 = typename make_integer_sequence_impl<T, M>::type; 258 using S2 = typename append_integer_sequence<S1, S1>::type; 259 using S3 = typename make_integer_sequence_impl<T, R>::type; 260 using S4 = typename append_integer_sequence<S2, S3>::type; 261 262 public: 263 264 using type = S4; 265 }; 266 267 template<class T, T N> struct make_integer_sequence_impl: iseq_if_c<N == 0, iseq_identity<integer_sequence<T>>, iseq_if_c<N == 1, iseq_identity<integer_sequence<T, 0>>, make_integer_sequence_impl_<T, N> > > 268 { 269 }; 270 271 } // namespace detail 272 273 // make_integer_sequence 274 template<class T, T N> using make_integer_sequence = typename detail::make_integer_sequence_impl<T, N>::type; 275 276 // index_sequence 277 template<std::size_t... I> using index_sequence = integer_sequence<std::size_t, I...>; 278 279 // make_index_sequence 280 template<std::size_t N> using make_index_sequence = make_integer_sequence<std::size_t, N>; 281 282 // index_sequence_for 283 template<class... T> using index_sequence_for = make_integer_sequence<std::size_t, sizeof...(T)>; 284 285 // implementation by Bruno Dutra (by the name is_evaluable) 286 namespace detail 287 { 288 289 template<template<class...> class F, class... T> struct mp_valid_impl 290 { 291 template<template<class...> class G, class = G<T...>> static mp_true check(int); 292 template<template<class...> class> static mp_false check(...); 293 294 using type = decltype(check<F>(0)); 295 }; 296 297 } // namespace detail 298 299 template<template<class...> class F, class... T> using mp_valid = typename detail::mp_valid_impl<F, T...>::type; 300 301 } } } 302 303 #endif 304