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 template <class _Ty>
35 using __decay_t = __decay(_Ty);
36 
37 #elif STDEXEC_NVHPC()
38 
39 template <class _Ty>
40 using __decay_t = std::decay_t<_Ty>;
41 
42 #else
43 
44 namespace __tt
45 {
46 struct __decay_object
47 {
48     template <class _Ty>
49     static _Ty __g(const _Ty&);
50     template <class _Ty>
51     using __f = decltype(__g(__declval<_Ty>()));
52 };
53 
54 struct __decay_default
55 {
56     template <class _Ty>
57     static _Ty __g(_Ty);
58     template <class _Ty>
59     using __f = decltype(__g(__declval<_Ty>()));
60 };
61 
62 struct __decay_abominable
63 {
64     template <class _Ty>
65     using __f = _Ty;
66 };
67 
68 struct __decay_void
69 {
70     template <class _Ty>
71     using __f = void;
72 };
73 
74 template <class _Ty>
75 extern __decay_object __mdecay;
76 
77 template <class _Ty, class... Us>
78 extern __decay_default __mdecay<_Ty(Us...)>;
79 
80 template <class _Ty, class... Us>
81 extern __decay_default __mdecay<_Ty(Us...) noexcept>;
82 
83 template <class _Ty, class... Us>
84 extern __decay_default __mdecay<_Ty (&)(Us...)>;
85 
86 template <class _Ty, class... Us>
87 extern __decay_default __mdecay<_Ty (&)(Us...) noexcept>;
88 
89 template <class _Ty, class... Us>
90 extern __decay_abominable __mdecay<_Ty(Us...) const>;
91 
92 template <class _Ty, class... Us>
93 extern __decay_abominable __mdecay<_Ty(Us...) const noexcept>;
94 
95 template <class _Ty, class... Us>
96 extern __decay_abominable __mdecay<_Ty(Us...) const&>;
97 
98 template <class _Ty, class... Us>
99 extern __decay_abominable __mdecay<_Ty(Us...) const & noexcept>;
100 
101 template <class _Ty, class... Us>
102 extern __decay_abominable __mdecay<_Ty(Us...) const&&>;
103 
104 template <class _Ty, class... Us>
105 extern __decay_abominable __mdecay<_Ty(Us...) const && noexcept>;
106 
107 template <class _Ty>
108 extern __decay_default __mdecay<_Ty[]>;
109 
110 template <class _Ty, std::size_t N>
111 extern __decay_default __mdecay<_Ty[N]>;
112 
113 template <class _Ty, std::size_t N>
114 extern __decay_default __mdecay<_Ty (&)[N]>;
115 
116 template <>
117 inline __decay_void __mdecay<void>;
118 
119 template <>
120 inline __decay_void __mdecay<const void>;
121 } // namespace __tt
122 
123 template <class _Ty>
124 using __decay_t = typename decltype(__tt::__mdecay<_Ty>)::template __f<_Ty>;
125 
126 #endif
127 
128 //////////////////////////////////////////////////////////////////////////////////////////////////
129 // __copy_cvref_t: For copying cvref from one type to another
130 struct __cp
131 {
132     template <class _Tp>
133     using __f = _Tp;
134 };
135 
136 struct __cpc
137 {
138     template <class _Tp>
139     using __f = const _Tp;
140 };
141 
142 struct __cplr
143 {
144     template <class _Tp>
145     using __f = _Tp&;
146 };
147 
148 struct __cprr
149 {
150     template <class _Tp>
151     using __f = _Tp&&;
152 };
153 
154 struct __cpclr
155 {
156     template <class _Tp>
157     using __f = const _Tp&;
158 };
159 
160 struct __cpcrr
161 {
162     template <class _Tp>
163     using __f = const _Tp&&;
164 };
165 
166 template <class>
167 extern __cp __cpcvr;
168 template <class _Tp>
169 extern __cpc __cpcvr<const _Tp>;
170 template <class _Tp>
171 extern __cplr __cpcvr<_Tp&>;
172 template <class _Tp>
173 extern __cprr __cpcvr<_Tp&&>;
174 template <class _Tp>
175 extern __cpclr __cpcvr<const _Tp&>;
176 template <class _Tp>
177 extern __cpcrr __cpcvr<const _Tp&&>;
178 template <class _Tp>
179 using __copy_cvref_fn = decltype(__cpcvr<_Tp>);
180 
181 template <class _From, class _To>
182 using __copy_cvref_t = typename __copy_cvref_fn<_From>::template __f<_To>;
183 
184 template <class>
185 inline constexpr bool __is_const_ = false;
186 template <class _Up>
187 inline constexpr bool __is_const_<const _Up> = true;
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 // Implemented as a class instead of a free function
200 // because of a bizarre nvc++ compiler bug:
201 struct __cref_fn
202 {
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 } // namespace stdexec
209