1 #ifndef BOOST_MP11_LIST_HPP_INCLUDED 2 #define BOOST_MP11_LIST_HPP_INCLUDED 3 4 // Copyright 2015-2017 Peter Dimov. 5 // 6 // Distributed under the Boost Software License, Version 1.0. 7 // 8 // See accompanying file LICENSE_1_0.txt or copy at 9 // http://www.boost.org/LICENSE_1_0.txt 10 11 #include <boost/mp11/integral.hpp> 12 #include <boost/mp11/detail/mp_list.hpp> 13 #include <boost/mp11/detail/mp_is_list.hpp> 14 #include <boost/mp11/detail/mp_append.hpp> 15 #include <boost/mp11/detail/config.hpp> 16 #include <type_traits> 17 18 namespace boost 19 { 20 namespace mp11 21 { 22 23 // mp_list_c<T, I...> 24 template<class T, T... I> using mp_list_c = mp_list<std::integral_constant<T, I>...>; 25 26 // mp_is_list<L> 27 // in detail/mp_is_list.hpp 28 29 // mp_size<L> 30 namespace detail 31 { 32 33 template<class L> struct mp_size_impl 34 { 35 // An error "no type named 'type'" here means that the argument to mp_size is not a list 36 }; 37 38 template<template<class...> class L, class... T> struct mp_size_impl<L<T...>> 39 { 40 using type = mp_size_t<sizeof...(T)>; 41 }; 42 43 } // namespace detail 44 45 template<class L> using mp_size = typename detail::mp_size_impl<L>::type; 46 47 // mp_empty<L> 48 template<class L> using mp_empty = mp_bool< mp_size<L>::value == 0 >; 49 50 // mp_assign<L1, L2> 51 namespace detail 52 { 53 54 template<class L1, class L2> struct mp_assign_impl; 55 56 template<template<class...> class L1, class... T, template<class...> class L2, class... U> struct mp_assign_impl<L1<T...>, L2<U...>> 57 { 58 using type = L1<U...>; 59 }; 60 61 } // namespace detail 62 63 template<class L1, class L2> using mp_assign = typename detail::mp_assign_impl<L1, L2>::type; 64 65 // mp_clear<L> 66 template<class L> using mp_clear = mp_assign<L, mp_list<>>; 67 68 // mp_front<L> 69 namespace detail 70 { 71 72 template<class L> struct mp_front_impl 73 { 74 // An error "no type named 'type'" here means that the argument to mp_front 75 // is either not a list, or is an empty list 76 }; 77 78 template<template<class...> class L, class T1, class... T> struct mp_front_impl<L<T1, T...>> 79 { 80 using type = T1; 81 }; 82 83 } // namespace detail 84 85 template<class L> using mp_front = typename detail::mp_front_impl<L>::type; 86 87 // mp_pop_front<L> 88 namespace detail 89 { 90 91 template<class L> struct mp_pop_front_impl 92 { 93 // An error "no type named 'type'" here means that the argument to mp_pop_front 94 // is either not a list, or is an empty list 95 }; 96 97 template<template<class...> class L, class T1, class... T> struct mp_pop_front_impl<L<T1, T...>> 98 { 99 using type = L<T...>; 100 }; 101 102 } // namespace detail 103 104 template<class L> using mp_pop_front = typename detail::mp_pop_front_impl<L>::type; 105 106 // mp_first<L> 107 template<class L> using mp_first = mp_front<L>; 108 109 // mp_rest<L> 110 template<class L> using mp_rest = mp_pop_front<L>; 111 112 // mp_second<L> 113 namespace detail 114 { 115 116 template<class L> struct mp_second_impl 117 { 118 // An error "no type named 'type'" here means that the argument to mp_second 119 // is either not a list, or has fewer than two elements 120 }; 121 122 template<template<class...> class L, class T1, class T2, class... T> struct mp_second_impl<L<T1, T2, T...>> 123 { 124 using type = T2; 125 }; 126 127 } // namespace detail 128 129 template<class L> using mp_second = typename detail::mp_second_impl<L>::type; 130 131 // mp_third<L> 132 namespace detail 133 { 134 135 template<class L> struct mp_third_impl 136 { 137 // An error "no type named 'type'" here means that the argument to mp_third 138 // is either not a list, or has fewer than three elements 139 }; 140 141 template<template<class...> class L, class T1, class T2, class T3, class... T> struct mp_third_impl<L<T1, T2, T3, T...>> 142 { 143 using type = T3; 144 }; 145 146 } // namespace detail 147 148 template<class L> using mp_third = typename detail::mp_third_impl<L>::type; 149 150 // mp_push_front<L, T...> 151 namespace detail 152 { 153 154 template<class L, class... T> struct mp_push_front_impl 155 { 156 // An error "no type named 'type'" here means that the first argument to mp_push_front is not a list 157 }; 158 159 template<template<class...> class L, class... U, class... T> struct mp_push_front_impl<L<U...>, T...> 160 { 161 using type = L<T..., U...>; 162 }; 163 164 } // namespace detail 165 166 template<class L, class... T> using mp_push_front = typename detail::mp_push_front_impl<L, T...>::type; 167 168 // mp_push_back<L, T...> 169 namespace detail 170 { 171 172 template<class L, class... T> struct mp_push_back_impl 173 { 174 // An error "no type named 'type'" here means that the first argument to mp_push_back is not a list 175 }; 176 177 template<template<class...> class L, class... U, class... T> struct mp_push_back_impl<L<U...>, T...> 178 { 179 using type = L<U..., T...>; 180 }; 181 182 } // namespace detail 183 184 template<class L, class... T> using mp_push_back = typename detail::mp_push_back_impl<L, T...>::type; 185 186 // mp_rename<L, B> 187 namespace detail 188 { 189 190 template<class A, template<class...> class B> struct mp_rename_impl 191 { 192 // An error "no type named 'type'" here means that the first argument to mp_rename is not a list 193 }; 194 195 template<template<class...> class A, class... T, template<class...> class B> struct mp_rename_impl<A<T...>, B> 196 { 197 using type = B<T...>; 198 }; 199 200 } // namespace detail 201 202 template<class A, template<class...> class B> using mp_rename = typename detail::mp_rename_impl<A, B>::type; 203 204 template<template<class...> class F, class L> using mp_apply = typename detail::mp_rename_impl<L, F>::type; 205 206 template<class Q, class L> using mp_apply_q = typename detail::mp_rename_impl<L, Q::template fn>::type; 207 208 // mp_replace_front<L, T> 209 namespace detail 210 { 211 212 template<class L, class T> struct mp_replace_front_impl 213 { 214 // An error "no type named 'type'" here means that the first argument to mp_replace_front 215 // is either not a list, or is an empty list 216 }; 217 218 template<template<class...> class L, class U1, class... U, class T> struct mp_replace_front_impl<L<U1, U...>, T> 219 { 220 using type = L<T, U...>; 221 }; 222 223 } // namespace detail 224 225 template<class L, class T> using mp_replace_front = typename detail::mp_replace_front_impl<L, T>::type; 226 227 // mp_replace_first<L, T> 228 template<class L, class T> using mp_replace_first = typename detail::mp_replace_front_impl<L, T>::type; 229 230 // mp_replace_second<L, T> 231 namespace detail 232 { 233 234 template<class L, class T> struct mp_replace_second_impl 235 { 236 // An error "no type named 'type'" here means that the first argument to mp_replace_second 237 // is either not a list, or has fewer than two elements 238 }; 239 240 template<template<class...> class L, class U1, class U2, class... U, class T> struct mp_replace_second_impl<L<U1, U2, U...>, T> 241 { 242 using type = L<U1, T, U...>; 243 }; 244 245 } // namespace detail 246 247 template<class L, class T> using mp_replace_second = typename detail::mp_replace_second_impl<L, T>::type; 248 249 // mp_replace_third<L, T> 250 namespace detail 251 { 252 253 template<class L, class T> struct mp_replace_third_impl 254 { 255 // An error "no type named 'type'" here means that the first argument to mp_replace_third 256 // is either not a list, or has fewer than three elements 257 }; 258 259 template<template<class...> class L, class U1, class U2, class U3, class... U, class T> struct mp_replace_third_impl<L<U1, U2, U3, U...>, T> 260 { 261 using type = L<U1, U2, T, U...>; 262 }; 263 264 } // namespace detail 265 266 template<class L, class T> using mp_replace_third = typename detail::mp_replace_third_impl<L, T>::type; 267 268 // mp_transform_front<L, F> 269 namespace detail 270 { 271 272 template<class L, template<class...> class F> struct mp_transform_front_impl 273 { 274 // An error "no type named 'type'" here means that the first argument to mp_transform_front 275 // is either not a list, or is an empty list 276 }; 277 278 template<template<class...> class L, class U1, class... U, template<class...> class F> struct mp_transform_front_impl<L<U1, U...>, F> 279 { 280 using type = L<F<U1>, U...>; 281 }; 282 283 } // namespace detail 284 285 template<class L, template<class...> class F> using mp_transform_front = typename detail::mp_transform_front_impl<L, F>::type; 286 template<class L, class Q> using mp_transform_front_q = mp_transform_front<L, Q::template fn>; 287 288 // mp_transform_first<L, F> 289 template<class L, template<class...> class F> using mp_transform_first = typename detail::mp_transform_front_impl<L, F>::type; 290 template<class L, class Q> using mp_transform_first_q = mp_transform_first<L, Q::template fn>; 291 292 // mp_transform_second<L, F> 293 namespace detail 294 { 295 296 template<class L, template<class...> class F> struct mp_transform_second_impl 297 { 298 // An error "no type named 'type'" here means that the first argument to mp_transform_second 299 // is either not a list, or has fewer than two elements 300 }; 301 302 template<template<class...> class L, class U1, class U2, class... U, template<class...> class F> struct mp_transform_second_impl<L<U1, U2, U...>, F> 303 { 304 using type = L<U1, F<U2>, U...>; 305 }; 306 307 } // namespace detail 308 309 template<class L, template<class...> class F> using mp_transform_second = typename detail::mp_transform_second_impl<L, F>::type; 310 template<class L, class Q> using mp_transform_second_q = mp_transform_second<L, Q::template fn>; 311 312 // mp_transform_third<L, F> 313 namespace detail 314 { 315 316 template<class L, template<class...> class F> struct mp_transform_third_impl 317 { 318 // An error "no type named 'type'" here means that the first argument to mp_transform_third 319 // is either not a list, or has fewer than three elements 320 }; 321 322 template<template<class...> class L, class U1, class U2, class U3, class... U, template<class...> class F> struct mp_transform_third_impl<L<U1, U2, U3, U...>, F> 323 { 324 using type = L<U1, U2, F<U3>, U...>; 325 }; 326 327 } // namespace detail 328 329 template<class L, template<class...> class F> using mp_transform_third = typename detail::mp_transform_third_impl<L, F>::type; 330 template<class L, class Q> using mp_transform_third_q = mp_transform_third<L, Q::template fn>; 331 332 } // namespace mp11 333 } // namespace boost 334 335 #endif // #ifndef BOOST_MP11_LIST_HPP_INCLUDED 336