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