1 #ifndef BOOST_MP11_UTILITY_HPP_INCLUDED 2 #define BOOST_MP11_UTILITY_HPP_INCLUDED 3 4 // Copyright 2015-2020 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_fold.hpp> 14 #include <boost/mp11/detail/config.hpp> 15 16 namespace boost 17 { 18 namespace mp11 19 { 20 21 // mp_identity 22 template<class T> struct mp_identity 23 { 24 using type = T; 25 }; 26 27 // mp_identity_t 28 template<class T> using mp_identity_t = typename mp_identity<T>::type; 29 30 // mp_inherit 31 template<class... T> struct mp_inherit: T... {}; 32 33 // mp_if, mp_if_c 34 namespace detail 35 { 36 37 template<bool C, class T, class... E> struct mp_if_c_impl 38 { 39 }; 40 41 template<class T, class... E> struct mp_if_c_impl<true, T, E...> 42 { 43 using type = T; 44 }; 45 46 template<class T, class E> struct mp_if_c_impl<false, T, E> 47 { 48 using type = E; 49 }; 50 51 } // namespace detail 52 53 template<bool C, class T, class... E> using mp_if_c = typename detail::mp_if_c_impl<C, T, E...>::type; 54 template<class C, class T, class... E> using mp_if = typename detail::mp_if_c_impl<static_cast<bool>(C::value), T, E...>::type; 55 56 // mp_valid 57 58 #if BOOST_MP11_WORKAROUND( BOOST_MP11_INTEL, != 0 ) // tested at 1800 59 60 // contributed by Roland Schulz in https://github.com/boostorg/mp11/issues/17 61 62 namespace detail 63 { 64 65 template<class...> using void_t = void; 66 67 template<class, template<class...> class F, class... T> 68 struct mp_valid_impl: mp_false {}; 69 70 template<template<class...> class F, class... T> 71 struct mp_valid_impl<void_t<F<T...>>, F, T...>: mp_true {}; 72 73 } // namespace detail 74 75 template<template<class...> class F, class... T> using mp_valid = typename detail::mp_valid_impl<void, F, T...>; 76 77 #else 78 79 // implementation by Bruno Dutra (by the name is_evaluable) 80 namespace detail 81 { 82 83 template<template<class...> class F, class... T> struct mp_valid_impl 84 { 85 template<template<class...> class G, class = G<T...>> static mp_true check(int); 86 template<template<class...> class> static mp_false check(...); 87 88 using type = decltype(check<F>(0)); 89 }; 90 91 } // namespace detail 92 93 template<template<class...> class F, class... T> using mp_valid = typename detail::mp_valid_impl<F, T...>::type; 94 95 #endif 96 97 template<class Q, class... T> using mp_valid_q = mp_valid<Q::template fn, T...>; 98 99 // mp_defer 100 namespace detail 101 { 102 103 template<template<class...> class F, class... T> struct mp_defer_impl 104 { 105 using type = F<T...>; 106 }; 107 108 struct mp_no_type 109 { 110 }; 111 112 #if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 ) 113 114 template<template<class...> class F, class... T> struct mp_defer_cuda_workaround 115 { 116 using type = mp_if<mp_valid<F, T...>, detail::mp_defer_impl<F, T...>, detail::mp_no_type>; 117 }; 118 119 #endif 120 121 } // namespace detail 122 123 #if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 ) 124 125 template<template<class...> class F, class... T> using mp_defer = typename detail::mp_defer_cuda_workaround< F, T...>::type; 126 127 #else 128 129 template<template<class...> class F, class... T> using mp_defer = mp_if<mp_valid<F, T...>, detail::mp_defer_impl<F, T...>, detail::mp_no_type>; 130 131 #endif 132 133 // mp_eval_if, mp_eval_if_c 134 namespace detail 135 { 136 137 template<bool C, class T, template<class...> class F, class... U> struct mp_eval_if_c_impl; 138 139 template<class T, template<class...> class F, class... U> struct mp_eval_if_c_impl<true, T, F, U...> 140 { 141 using type = T; 142 }; 143 144 template<class T, template<class...> class F, class... U> struct mp_eval_if_c_impl<false, T, F, U...>: mp_defer<F, U...> 145 { 146 }; 147 148 } // namespace detail 149 150 template<bool C, class T, template<class...> class F, class... U> using mp_eval_if_c = typename detail::mp_eval_if_c_impl<C, T, F, U...>::type; 151 template<class C, class T, template<class...> class F, class... U> using mp_eval_if = typename detail::mp_eval_if_c_impl<static_cast<bool>(C::value), T, F, U...>::type; 152 template<class C, class T, class Q, class... U> using mp_eval_if_q = typename detail::mp_eval_if_c_impl<static_cast<bool>(C::value), T, Q::template fn, U...>::type; 153 154 // mp_eval_if_not 155 template<class C, class T, template<class...> class F, class... U> using mp_eval_if_not = mp_eval_if<mp_not<C>, T, F, U...>; 156 template<class C, class T, class Q, class... U> using mp_eval_if_not_q = mp_eval_if<mp_not<C>, T, Q::template fn, U...>; 157 158 // mp_eval_or 159 template<class T, template<class...> class F, class... U> using mp_eval_or = mp_eval_if_not<mp_valid<F, U...>, T, F, U...>; 160 template<class T, class Q, class... U> using mp_eval_or_q = mp_eval_or<T, Q::template fn, U...>; 161 162 // mp_cond 163 164 // so elegant; so doesn't work 165 // template<class C, class T, class... E> using mp_cond = mp_eval_if<C, T, mp_cond, E...>; 166 167 namespace detail 168 { 169 170 template<class C, class T, class... E> struct mp_cond_impl; 171 172 } // namespace detail 173 174 template<class C, class T, class... E> using mp_cond = typename detail::mp_cond_impl<C, T, E...>::type; 175 176 namespace detail 177 { 178 179 template<class C, class T, class... E> using mp_cond_ = mp_eval_if<C, T, mp_cond, E...>; 180 181 template<class C, class T, class... E> struct mp_cond_impl: mp_defer<mp_cond_, C, T, E...> 182 { 183 }; 184 185 } // namespace detail 186 187 // mp_quote 188 template<template<class...> class F> struct mp_quote 189 { 190 // the indirection through mp_defer works around the language inability 191 // to expand T... into a fixed parameter list of an alias template 192 193 template<class... T> using fn = typename mp_defer<F, T...>::type; 194 }; 195 196 // mp_quote_trait 197 template<template<class...> class F> struct mp_quote_trait 198 { 199 template<class... T> using fn = typename F<T...>::type; 200 }; 201 202 // mp_invoke_q 203 #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1900 ) 204 205 namespace detail 206 { 207 208 template<class Q, class... T> struct mp_invoke_q_impl: mp_defer<Q::template fn, T...> {}; 209 210 } // namespace detail 211 212 template<class Q, class... T> using mp_invoke_q = typename detail::mp_invoke_q_impl<Q, T...>::type; 213 214 #elif BOOST_MP11_WORKAROUND( BOOST_MP11_GCC, < 50000 ) 215 216 template<class Q, class... T> using mp_invoke_q = typename mp_defer<Q::template fn, T...>::type; 217 218 #else 219 220 template<class Q, class... T> using mp_invoke_q = typename Q::template fn<T...>; 221 222 #endif 223 224 // old name for mp_invoke_q retained for compatibility, but deprecated 225 #if !defined(__clang__) 226 227 template<class Q, class... T> using mp_invoke BOOST_MP11_DEPRECATED("please use mp_invoke_q") = mp_invoke_q<Q, T...>; 228 229 #else 230 231 // Clang doesn't warn on deprecated alias templates 232 233 template<class Q, class... T> struct BOOST_MP11_DEPRECATED("please use mp_invoke_q") mp_invoke_ 234 { 235 using type = mp_invoke_q<Q, T...>; 236 }; 237 238 template<class Q, class... T> using mp_invoke = typename mp_invoke_<Q, T...>::type; 239 240 #endif 241 242 // mp_not_fn<P> 243 template<template<class...> class P> struct mp_not_fn 244 { 245 template<class... T> using fn = mp_not< mp_invoke_q<mp_quote<P>, T...> >; 246 }; 247 248 template<class Q> using mp_not_fn_q = mp_not_fn<Q::template fn>; 249 250 // mp_compose 251 namespace detail 252 { 253 254 template<class T, class Q> using mp_reverse_invoke_q = mp_invoke_q<Q, T>; 255 256 } // namespace detail 257 258 #if !BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1900 ) 259 260 template<template<class...> class... F> struct mp_compose 261 { 262 template<class T> using fn = mp_fold<mp_list<mp_quote<F>...>, T, detail::mp_reverse_invoke_q>; 263 }; 264 265 #endif 266 267 template<class... Q> struct mp_compose_q 268 { 269 template<class T> using fn = mp_fold<mp_list<Q...>, T, detail::mp_reverse_invoke_q>; 270 }; 271 272 } // namespace mp11 273 } // namespace boost 274 275 #endif // #ifndef BOOST_MP11_UTILITY_HPP_INCLUDED 276