1 /* 2 * Copyright (c) 2022 NVIDIA Corporation 3 * 4 * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 * (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * 8 * https://llvm.org/LICENSE.txt 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #pragma once 17 18 #include "__config.hpp" 19 20 #include <type_traits> // IWYU pragma: keep 21 #include <utility> // IWYU pragma: keep 22 23 namespace stdexec { 24 25 ////////////////////////////////////////////////////////////////////////////////////////////////// 26 // A very simple std::declval replacement that doesn't handle void 27 template <class _Tp, bool _Noexcept = true> 28 using __declfn = auto (*)() noexcept(_Noexcept) -> _Tp; 29 30 template <class _Tp> 31 extern __declfn<_Tp &&> __declval; 32 33 ////////////////////////////////////////////////////////////////////////////////////////////////// 34 // __decay_t: An efficient implementation for std::decay 35 #if STDEXEC_HAS_BUILTIN(__decay) 36 37 namespace __tt { 38 template <class> 39 struct __wrap; 40 41 template <bool> 42 struct __decay_ { 43 template <class _Ty> 44 using __f = __decay(_Ty); 45 }; 46 } // namespace __tt 47 template <class _Ty> 48 using __decay_t = __tt::__decay_<sizeof(__tt::__wrap<_Ty> *) == ~0ul>::template __f<_Ty>; 49 50 #elif STDEXEC_EDG() 51 52 template <class _Ty> 53 using __decay_t = std::decay_t<_Ty>; 54 55 #else 56 57 namespace __tt { 58 struct __decay_object { 59 template <class _Ty> 60 static _Ty __g(_Ty const &); 61 template <class _Ty> 62 using __f = decltype(__g(__declval<_Ty>())); 63 }; 64 65 struct __decay_default { 66 template <class _Ty> 67 static _Ty __g(_Ty); 68 template <class _Ty> 69 using __f = decltype(__g(__declval<_Ty>())); 70 }; 71 72 struct __decay_abominable { 73 template <class _Ty> 74 using __f = _Ty; 75 }; 76 77 struct __decay_void { 78 template <class _Ty> 79 using __f = void; 80 }; 81 82 template <class _Ty> 83 extern __decay_object __mdecay; 84 85 template <class _Ty, class... Us> 86 extern __decay_default __mdecay<_Ty(Us...)>; 87 88 template <class _Ty, class... Us> 89 extern __decay_default __mdecay<_Ty(Us...) noexcept>; 90 91 template <class _Ty, class... Us> 92 extern __decay_default __mdecay<_Ty (&)(Us...)>; 93 94 template <class _Ty, class... Us> 95 extern __decay_default __mdecay<_Ty (&)(Us...) noexcept>; 96 97 template <class _Ty, class... Us> 98 extern __decay_abominable __mdecay<_Ty(Us...) const>; 99 100 template <class _Ty, class... Us> 101 extern __decay_abominable __mdecay<_Ty(Us...) const noexcept>; 102 103 template <class _Ty, class... Us> 104 extern __decay_abominable __mdecay<_Ty(Us...) const &>; 105 106 template <class _Ty, class... Us> 107 extern __decay_abominable __mdecay<_Ty(Us...) const & noexcept>; 108 109 template <class _Ty, class... Us> 110 extern __decay_abominable __mdecay<_Ty(Us...) const &&>; 111 112 template <class _Ty, class... Us> 113 extern __decay_abominable __mdecay<_Ty(Us...) const && noexcept>; 114 115 template <class _Ty> 116 extern __decay_default __mdecay<_Ty[]>; 117 118 template <class _Ty, std::size_t N> 119 extern __decay_default __mdecay<_Ty[N]>; 120 121 template <class _Ty, std::size_t N> 122 extern __decay_default __mdecay<_Ty (&)[N]>; 123 124 template <> 125 inline __decay_void __mdecay<void>; 126 127 template <> 128 inline __decay_void __mdecay<void const>; 129 } // namespace __tt 130 131 template <class _Ty> 132 using __decay_t = decltype(__tt::__mdecay<_Ty>)::template __f<_Ty>; 133 134 #endif 135 136 ////////////////////////////////////////////////////////////////////////////////////////////////// 137 // __copy_cvref_t: For copying cvref from one type to another 138 struct __cp { 139 template <class _Tp> 140 using __f = _Tp; 141 }; 142 143 struct __cpc { 144 template <class _Tp> 145 using __f = const _Tp; 146 }; 147 148 struct __cplr { 149 template <class _Tp> 150 using __f = _Tp &; 151 }; 152 153 struct __cprr { 154 template <class _Tp> 155 using __f = _Tp &&; 156 }; 157 158 struct __cpclr { 159 template <class _Tp> 160 using __f = const _Tp &; 161 }; 162 163 struct __cpcrr { 164 template <class _Tp> 165 using __f = const _Tp &&; 166 }; 167 168 template <class> 169 extern __cp __cpcvr; 170 template <class _Tp> 171 extern __cpc __cpcvr<const _Tp>; 172 template <class _Tp> 173 extern __cplr __cpcvr<_Tp &>; 174 template <class _Tp> 175 extern __cprr __cpcvr<_Tp &&>; 176 template <class _Tp> 177 extern __cpclr __cpcvr<const _Tp &>; 178 template <class _Tp> 179 extern __cpcrr __cpcvr<const _Tp &&>; 180 template <class _Tp> 181 using __copy_cvref_fn = decltype(__cpcvr<_Tp>); 182 183 template <class _From, class _To> 184 using __copy_cvref_t = __copy_cvref_fn<_From>::template __f<_To>; 185 186 template <class> 187 inline constexpr bool __is_const_ = false; 188 template <class _Up> 189 inline constexpr bool __is_const_<_Up const> = true; 190 191 namespace __tt { 192 template <class _Ty> 193 auto __remove_rvalue_reference_fn(_Ty &&) -> _Ty; 194 } // namespace __tt 195 196 template <class _Ty> 197 using __remove_rvalue_reference_t = decltype(__tt::__remove_rvalue_reference_fn( 198 __declval<_Ty>())); 199 200 // Implemented as a class instead of a free function 201 // because of a bizarre nvc++ compiler bug: 202 struct __cref_fn { 203 template <class _Ty> 204 auto operator()(const _Ty &) -> const _Ty &; 205 }; 206 template <class _Ty> 207 using __cref_t = decltype(__cref_fn{}(__declval<_Ty>())); 208 209 // Because of nvc++ nvbugs#4679848, we can't make __mbool a simple alias for __mconstant, 210 // and because of nvc++ nvbugs#4668709 it can't be a simple alias for std::bool_constant, 211 // either. :-( 212 // template <bool _Bp> 213 // using __mbool = __mconstant<_Bp>; 214 215 template <bool _Bp> 216 struct __mbool : std::bool_constant<_Bp> { }; 217 218 using __mtrue = __mbool<true>; 219 using __mfalse = __mbool<false>; 220 221 } // namespace stdexec 222