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> 21 22 namespace stdexec 23 { 24 25 ////////////////////////////////////////////////////////////////////////////////////////////////// 26 // A very simple std::declval replacement that doesn't handle void 27 template <class _Tp> 28 extern auto (*__declval)() noexcept -> _Tp&&; 29 30 ////////////////////////////////////////////////////////////////////////////////////////////////// 31 // __decay_t: An efficient implementation for std::decay 32 #if STDEXEC_HAS_BUILTIN(__decay) 33 34 namespace __tt 35 { 36 template <class> 37 struct __wrap; 38 39 template <bool> 40 struct __decay_ 41 { 42 template <class _Ty> 43 using __f = __decay(_Ty); 44 }; 45 } // namespace __tt 46 template <class _Ty> 47 using __decay_t = typename __tt::__decay_<sizeof(__tt::__wrap<_Ty>*) == 48 ~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 { 59 struct __decay_object 60 { 61 template <class _Ty> 62 static _Ty __g(const _Ty&); 63 template <class _Ty> 64 using __f = decltype(__g(__declval<_Ty>())); 65 }; 66 67 struct __decay_default 68 { 69 template <class _Ty> 70 static _Ty __g(_Ty); 71 template <class _Ty> 72 using __f = decltype(__g(__declval<_Ty>())); 73 }; 74 75 struct __decay_abominable 76 { 77 template <class _Ty> 78 using __f = _Ty; 79 }; 80 81 struct __decay_void 82 { 83 template <class _Ty> 84 using __f = void; 85 }; 86 87 template <class _Ty> 88 extern __decay_object __mdecay; 89 90 template <class _Ty, class... Us> 91 extern __decay_default __mdecay<_Ty(Us...)>; 92 93 template <class _Ty, class... Us> 94 extern __decay_default __mdecay<_Ty(Us...) noexcept>; 95 96 template <class _Ty, class... Us> 97 extern __decay_default __mdecay<_Ty (&)(Us...)>; 98 99 template <class _Ty, class... Us> 100 extern __decay_default __mdecay<_Ty (&)(Us...) noexcept>; 101 102 template <class _Ty, class... Us> 103 extern __decay_abominable __mdecay<_Ty(Us...) const>; 104 105 template <class _Ty, class... Us> 106 extern __decay_abominable __mdecay<_Ty(Us...) const noexcept>; 107 108 template <class _Ty, class... Us> 109 extern __decay_abominable __mdecay<_Ty(Us...) const&>; 110 111 template <class _Ty, class... Us> 112 extern __decay_abominable __mdecay<_Ty(Us...) const & noexcept>; 113 114 template <class _Ty, class... Us> 115 extern __decay_abominable __mdecay<_Ty(Us...) const&&>; 116 117 template <class _Ty, class... Us> 118 extern __decay_abominable __mdecay<_Ty(Us...) const && noexcept>; 119 120 template <class _Ty> 121 extern __decay_default __mdecay<_Ty[]>; 122 123 template <class _Ty, std::size_t N> 124 extern __decay_default __mdecay<_Ty[N]>; 125 126 template <class _Ty, std::size_t N> 127 extern __decay_default __mdecay<_Ty (&)[N]>; 128 129 template <> 130 inline __decay_void __mdecay<void>; 131 132 template <> 133 inline __decay_void __mdecay<const void>; 134 } // namespace __tt 135 136 template <class _Ty> 137 using __decay_t = typename decltype(__tt::__mdecay<_Ty>)::template __f<_Ty>; 138 139 #endif 140 141 ////////////////////////////////////////////////////////////////////////////////////////////////// 142 // __copy_cvref_t: For copying cvref from one type to another 143 struct __cp 144 { 145 template <class _Tp> 146 using __f = _Tp; 147 }; 148 149 struct __cpc 150 { 151 template <class _Tp> 152 using __f = const _Tp; 153 }; 154 155 struct __cplr 156 { 157 template <class _Tp> 158 using __f = _Tp&; 159 }; 160 161 struct __cprr 162 { 163 template <class _Tp> 164 using __f = _Tp&&; 165 }; 166 167 struct __cpclr 168 { 169 template <class _Tp> 170 using __f = const _Tp&; 171 }; 172 173 struct __cpcrr 174 { 175 template <class _Tp> 176 using __f = const _Tp&&; 177 }; 178 179 template <class> 180 extern __cp __cpcvr; 181 template <class _Tp> 182 extern __cpc __cpcvr<const _Tp>; 183 template <class _Tp> 184 extern __cplr __cpcvr<_Tp&>; 185 template <class _Tp> 186 extern __cprr __cpcvr<_Tp&&>; 187 template <class _Tp> 188 extern __cpclr __cpcvr<const _Tp&>; 189 template <class _Tp> 190 extern __cpcrr __cpcvr<const _Tp&&>; 191 template <class _Tp> 192 using __copy_cvref_fn = decltype(__cpcvr<_Tp>); 193 194 template <class _From, class _To> 195 using __copy_cvref_t = typename __copy_cvref_fn<_From>::template __f<_To>; 196 197 template <class> 198 inline constexpr bool __is_const_ = false; 199 template <class _Up> 200 inline constexpr bool __is_const_<const _Up> = true; 201 202 namespace __tt 203 { 204 template <class _Ty> 205 auto __remove_rvalue_reference_fn(_Ty&&) -> _Ty; 206 } // namespace __tt 207 208 template <class _Ty> 209 using __remove_rvalue_reference_t = 210 decltype(__tt::__remove_rvalue_reference_fn(__declval<_Ty>())); 211 212 // Implemented as a class instead of a free function 213 // because of a bizarre nvc++ compiler bug: 214 struct __cref_fn 215 { 216 template <class _Ty> 217 auto operator()(const _Ty&) -> const _Ty&; 218 }; 219 template <class _Ty> 220 using __cref_t = decltype(__cref_fn{}(__declval<_Ty>())); 221 } // namespace stdexec 222