xref: /openbmc/sdbusplus/include/sdbusplus/async/stdexec/__detail/__config.hpp (revision a4df19a74a398f3fb806a9c245f6bda42cfff117)
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 #if __cplusplus < 202002L
19 #error This library requires the use of C++20.
20 #endif
21 
22 #if __has_include(<version>)
23 #include <version>
24 #else
25 #include <ciso646> // For stdlib feature-test macros when <version> is not available
26 #endif
27 
28 #include <cassert>
29 #include <version>
30 
31 #define STDEXEC_STRINGIZE(_ARG) #_ARG
32 
33 #define STDEXEC_CAT_(_XP, ...) _XP##__VA_ARGS__
34 #define STDEXEC_CAT(_XP, ...) STDEXEC_CAT_(_XP, __VA_ARGS__)
35 
36 #define STDEXEC_EXPAND(...) __VA_ARGS__
37 #define STDEXEC_EVAL(_MACRO, ...) _MACRO(__VA_ARGS__)
38 #define STDEXEC_EAT(...)
39 
40 #define STDEXEC_NOT(_XP) STDEXEC_CAT(STDEXEC_NOT_, _XP)
41 #define STDEXEC_NOT_0 1
42 #define STDEXEC_NOT_1 0
43 
44 #define STDEXEC_IIF_0(_YP, ...) __VA_ARGS__
45 #define STDEXEC_IIF_1(_YP, ...) _YP
46 #define STDEXEC_IIF(_XP, _YP, ...)                                             \
47     STDEXEC_EVAL(STDEXEC_CAT(STDEXEC_IIF_, _XP), _YP, __VA_ARGS__)
48 
49 #define STDEXEC_COUNT(...)                                                     \
50     STDEXEC_EXPAND(STDEXEC_COUNT_(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1))
51 #define STDEXEC_COUNT_(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _NP, ...) _NP
52 
53 #define STDEXEC_CHECK(...) STDEXEC_EXPAND(STDEXEC_CHECK_(__VA_ARGS__, 0, ))
54 #define STDEXEC_CHECK_(_XP, _NP, ...) _NP
55 #define STDEXEC_PROBE(...) STDEXEC_PROBE_(__VA_ARGS__, 1)
56 #define STDEXEC_PROBE_(_XP, _NP, ...) _XP, _NP,
57 
58 ////////////////////////////////////////////////////////////////////////////////
59 // STDEXEC_FOR_EACH
60 //   Inspired by "Recursive macros with C++20 __VA_OPT__", by David Mazières
61 //   https://www.scs.stanford.edu/~dm/blog/va-opt.html
62 #define STDEXEC_EXPAND_R(...)                                                  \
63     STDEXEC_EXPAND_R1(                                                         \
64         STDEXEC_EXPAND_R1(STDEXEC_EXPAND_R1(STDEXEC_EXPAND_R1(__VA_ARGS__))))  \
65     /**/
66 #define STDEXEC_EXPAND_R1(...)                                                 \
67     STDEXEC_EXPAND_R2(                                                         \
68         STDEXEC_EXPAND_R2(STDEXEC_EXPAND_R2(STDEXEC_EXPAND_R2(__VA_ARGS__))))  \
69     /**/
70 #define STDEXEC_EXPAND_R2(...)                                                 \
71     STDEXEC_EXPAND_R3(                                                         \
72         STDEXEC_EXPAND_R3(STDEXEC_EXPAND_R3(STDEXEC_EXPAND_R3(__VA_ARGS__))))  \
73     /**/
74 #define STDEXEC_EXPAND_R3(...)                                                 \
75     STDEXEC_EXPAND(                                                            \
76         STDEXEC_EXPAND(STDEXEC_EXPAND(STDEXEC_EXPAND(__VA_ARGS__))))           \
77     /**/
78 
79 #define STDEXEC_PARENS ()
80 #define STDEXEC_FOR_EACH(_MACRO, ...)                                          \
81     __VA_OPT__(STDEXEC_EXPAND_R(STDEXEC_FOR_EACH_HELPER(_MACRO, __VA_ARGS__))) \
82     /**/
83 #define STDEXEC_FOR_EACH_HELPER(_MACRO, _A1, ...)                              \
84     _MACRO(_A1)                                                                \
85     __VA_OPT__(STDEXEC_FOR_EACH_AGAIN STDEXEC_PARENS(_MACRO, __VA_ARGS__)) /**/
86 #define STDEXEC_FOR_EACH_AGAIN() STDEXEC_FOR_EACH_HELPER
87 ////////////////////////////////////////////////////////////////////////////////////////////////////
88 
89 // If tail is non-empty, expand to the tail. Otherwise, expand to the head
90 #define STDEXEC_HEAD_OR_TAIL(_XP, ...)                                         \
91     STDEXEC_EXPAND __VA_OPT__((__VA_ARGS__)STDEXEC_EAT)(_XP)
92 
93 // If tail is non-empty, expand to nothing. Otherwise, expand to the head
94 #define STDEXEC_HEAD_OR_NULL(_XP, ...)                                         \
95     STDEXEC_EXPAND __VA_OPT__(() STDEXEC_EAT)(_XP)
96 
97 // When used with no arguments, these macros expand to 1 if the current
98 // compiler corresponds to the macro name; 0, otherwise. When used with
99 // arguments, they expand to the arguments if if the current compiler
100 // corresponds to the macro name; nothing, otherwise.
101 #if defined(__NVCC__)
102 #define STDEXEC_NVCC(...) STDEXEC_HEAD_OR_TAIL(1, __VA_ARGS__)
103 #elif defined(__NVCOMPILER)
104 #define STDEXEC_NVHPC(...) STDEXEC_HEAD_OR_TAIL(1, __VA_ARGS__)
105 #elif defined(__EDG__)
106 #define STDEXEC_EDG(...) STDEXEC_HEAD_OR_TAIL(1, __VA_ARGS__)
107 #elif defined(__clang__)
108 #define STDEXEC_CLANG(...) STDEXEC_HEAD_OR_TAIL(1, __VA_ARGS__)
109 #if defined(_MSC_VER)
110 #define STDEXEC_CLANG_CL(...) STDEXEC_HEAD_OR_TAIL(1, __VA_ARGS__)
111 #endif
112 #elif defined(__GNUC__)
113 #define STDEXEC_GCC(...) STDEXEC_HEAD_OR_TAIL(1, __VA_ARGS__)
114 #elif defined(_MSC_VER)
115 #define STDEXEC_MSVC(...) STDEXEC_HEAD_OR_TAIL(1, __VA_ARGS__)
116 #endif
117 
118 #ifndef STDEXEC_NVCC
119 #define STDEXEC_NVCC(...) STDEXEC_HEAD_OR_NULL(0, __VA_ARGS__)
120 #endif
121 #ifndef STDEXEC_NVHPC
122 #define STDEXEC_NVHPC(...) STDEXEC_HEAD_OR_NULL(0, __VA_ARGS__)
123 #endif
124 #ifndef STDEXEC_EDG
125 #define STDEXEC_EDG(...) STDEXEC_HEAD_OR_NULL(0, __VA_ARGS__)
126 #endif
127 #ifndef STDEXEC_CLANG
128 #define STDEXEC_CLANG(...) STDEXEC_HEAD_OR_NULL(0, __VA_ARGS__)
129 #endif
130 #ifndef STDEXEC_CLANG_CL
131 #define STDEXEC_CLANG_CL(...) STDEXEC_HEAD_OR_NULL(0, __VA_ARGS__)
132 #endif
133 #ifndef STDEXEC_GCC
134 #define STDEXEC_GCC(...) STDEXEC_HEAD_OR_NULL(0, __VA_ARGS__)
135 #endif
136 #ifndef STDEXEC_MSVC
137 #define STDEXEC_MSVC(...) STDEXEC_HEAD_OR_NULL(0, __VA_ARGS__)
138 #endif
139 
140 ////////////////////////////////////////////////////////////////////////////////////////////////////
141 #ifdef __CUDACC__
142 #define STDEXEC_CUDA(...) STDEXEC_HEAD_OR_TAIL(1, __VA_ARGS__)
143 #else
144 #define STDEXEC_CUDA(...) STDEXEC_HEAD_OR_NULL(0, __VA_ARGS__)
145 #endif
146 
147 ////////////////////////////////////////////////////////////////////////////////////////////////////
148 // For portably declaring attributes on functions and types
149 //   Usage:
150 //
151 //   STDEXEC_ATTRIBUTE((attr1, attr2, ...))
152 //   void foo() { ... }
153 #define STDEXEC_ATTRIBUTE(_XP)                                                 \
154     STDEXEC_FOR_EACH(STDEXEC_ATTR, STDEXEC_EXPAND _XP)
155 #define STDEXEC_ATTR(_ATTR)                                                    \
156     STDEXEC_CAT(STDEXEC_ATTR_WHICH_,                                           \
157                 STDEXEC_CHECK(STDEXEC_CAT(STDEXEC_ATTR_, _ATTR)))              \
158     (_ATTR)
159 
160 // unknown attributes are treated like C++-style attributes
161 #define STDEXEC_ATTR_WHICH_0(_ATTR) [[_ATTR]]
162 
163 // custom handling for specific attribute types
164 #ifdef __CUDACC__
165 #define STDEXEC_ATTR_WHICH_1(_ATTR) __host__
166 #else
167 #define STDEXEC_ATTR_WHICH_1(_ATTR)
168 #endif
169 #define STDEXEC_ATTR_host STDEXEC_PROBE(~, 1)
170 #define STDEXEC_ATTR___host__ STDEXEC_PROBE(~, 1)
171 
172 #ifdef __CUDACC__
173 #define STDEXEC_ATTR_WHICH_2(_ATTR) __device__
174 #else
175 #define STDEXEC_ATTR_WHICH_2(_ATTR)
176 #endif
177 #define STDEXEC_ATTR_device STDEXEC_PROBE(~, 2)
178 #define STDEXEC_ATTR___device__ STDEXEC_PROBE(~, 2)
179 
180 #if STDEXEC_NVHPC()
181 // NVBUG #4067067: NVHPC does not fully support [[no_unique_address]]
182 #define STDEXEC_ATTR_WHICH_3(_ATTR) /*nothing*/
183 #elif STDEXEC_MSVC()
184 // MSVCBUG
185 // https://developercommunity.visualstudio.com/t/Incorrect-codegen-when-using-msvc::no_/10452874
186 #define STDEXEC_ATTR_WHICH_3(_ATTR) // [[msvc::no_unique_address]]
187 #elif STDEXEC_CLANG_CL()
188 // clang-cl does not support: https://reviews.llvm.org/D110485
189 #define STDEXEC_ATTR_WHICH_3(_ATTR) // [[msvc::no_unique_address]]
190 #else
191 #define STDEXEC_ATTR_WHICH_3(_ATTR) [[no_unique_address]]
192 #endif
193 #define STDEXEC_ATTR_no_unique_address STDEXEC_PROBE(~, 3)
194 
195 #if STDEXEC_MSVC()
196 #define STDEXEC_ATTR_WHICH_4(_ATTR) __forceinline
197 #elif STDEXEC_CLANG()
198 #define STDEXEC_ATTR_WHICH_4(_ATTR)                                            \
199     __attribute__((__always_inline__, __artificial__, __nodebug__)) inline
200 #elif defined(__GNUC__)
201 #define STDEXEC_ATTR_WHICH_4(_ATTR)                                            \
202     __attribute__((__always_inline__, __artificial__)) inline
203 #else
204 #define STDEXEC_ATTR_WHICH_4(_ATTR) /*nothing*/
205 #endif
206 #define STDEXEC_ATTR_always_inline STDEXEC_PROBE(~, 4)
207 
208 ////////////////////////////////////////////////////////////////////////////////////////////////////
209 // warning push/pop portability macros
210 #if STDEXEC_NVCC()
211 #define STDEXEC_PRAGMA_PUSH() _Pragma("nv_diagnostic push")
212 #define STDEXEC_PRAGMA_POP() _Pragma("nv_diagnostic pop")
213 #define STDEXEC_PRAGMA_IGNORE_EDG(...)                                         \
214     _Pragma(STDEXEC_STRINGIZE(nv_diag_suppress __VA_ARGS__))
215 #elif STDEXEC_NVHPC() || STDEXEC_EDG()
216 #define STDEXEC_PRAGMA_PUSH()                                                  \
217     _Pragma("diagnostic push") STDEXEC_PRAGMA_IGNORE_EDG(invalid_error_number)
218 #define STDEXEC_PRAGMA_POP() _Pragma("diagnostic pop")
219 #define STDEXEC_PRAGMA_IGNORE_EDG(...)                                         \
220     _Pragma(STDEXEC_STRINGIZE(diag_suppress __VA_ARGS__))
221 #elif STDEXEC_CLANG() || STDEXEC_GCC()
222 #define STDEXEC_PRAGMA_PUSH()                                                  \
223     _Pragma("GCC diagnostic push") STDEXEC_PRAGMA_IGNORE_GNU("-Wpragmas")      \
224         STDEXEC_PRAGMA_IGNORE_GNU("-Wunknown-pragmas")                         \
225             STDEXEC_PRAGMA_IGNORE_GNU("-Wunknown-warning-option")              \
226                 STDEXEC_PRAGMA_IGNORE_GNU("-Wunknown-attributes")              \
227                     STDEXEC_PRAGMA_IGNORE_GNU("-Wattributes")
228 #define STDEXEC_PRAGMA_POP() _Pragma("GCC diagnostic pop")
229 #define STDEXEC_PRAGMA_IGNORE_GNU(...)                                         \
230     _Pragma(STDEXEC_STRINGIZE(GCC diagnostic ignored __VA_ARGS__))
231 #else
232 #define STDEXEC_PRAGMA_PUSH()
233 #define STDEXEC_PRAGMA_POP()
234 #endif
235 
236 #ifndef STDEXEC_PRAGMA_IGNORE_GNU
237 #define STDEXEC_PRAGMA_IGNORE_GNU(...)
238 #endif
239 #ifndef STDEXEC_PRAGMA_IGNORE_EDG
240 #define STDEXEC_PRAGMA_IGNORE_EDG(...)
241 #endif
242 
243 #if !STDEXEC_MSVC() && defined(__has_builtin)
244 #define STDEXEC_HAS_BUILTIN __has_builtin
245 #else
246 #define STDEXEC_HAS_BUILTIN(...) 0
247 #endif
248 
249 #if !STDEXEC_MSVC() && defined(__has_feature)
250 #define STDEXEC_HAS_FEATURE __has_feature
251 #else
252 #define STDEXEC_HAS_FEATURE(...) 0
253 #endif
254 
255 #if STDEXEC_HAS_BUILTIN(__is_trivially_copyable) || STDEXEC_MSVC()
256 #define STDEXEC_IS_TRIVIALLY_COPYABLE(...) __is_trivially_copyable(__VA_ARGS__)
257 #else
258 #define STDEXEC_IS_TRIVIALLY_COPYABLE(...)                                     \
259     std::is_trivially_copyable_v<__VA_ARGS__>
260 #endif
261 
262 #if STDEXEC_HAS_BUILTIN(__is_base_of) || (_MSC_VER >= 1914)
263 #define STDEXEC_IS_BASE_OF(...) __is_base_of(__VA_ARGS__)
264 #else
265 #define STDEXEC_IS_BASE_OF(...) std::is_base_of_v<__VA_ARGS__>
266 #endif
267 
268 #if STDEXEC_HAS_BUILTIN(__is_convertible_to) || STDEXEC_MSVC()
269 #define STDEXEC_IS_CONVERTIBLE_TO(...) __is_convertible_to(__VA_ARGS__)
270 #elif STDEXEC_HAS_BUILTIN(__is_convertible)
271 #define STDEXEC_IS_CONVERTIBLE_TO(...) __is_convertible(__VA_ARGS__)
272 #else
273 #define STDEXEC_IS_CONVERTIBLE_TO(...) std::is_convertible_v<__VA_ARGS__>
274 #endif
275 
276 #if STDEXEC_HAS_BUILTIN(__is_const)
277 #define STDEXEC_IS_CONST(...) __is_const(__VA_ARGS__)
278 #else
279 #define STDEXEC_IS_CONST(...) stdexec::__is_const<__VA_ARGS__>
280 #endif
281 
282 #if defined(__cpp_lib_unreachable) && __cpp_lib_unreachable >= 202202L
283 #define STDEXEC_UNREACHABLE() std::unreachable()
284 #elif STDEXEC_HAS_BUILTIN(__builtin_unreachable)
285 #define STDEXEC_UNREACHABLE() __builtin_unreachable()
286 #elif STDEXEC_MSVC()
287 #define STDEXEC_UNREACHABLE(...) __assume(false)
288 #else
289 #define STDEXEC_UNREACHABLE(...) std::terminate()
290 #endif
291 
292 // Before gcc-12, gcc really didn't like tuples or variants of immovable types
293 #if STDEXEC_GCC() && (__GNUC__ < 12)
294 #define STDEXEC_IMMOVABLE(_XP) _XP(_XP&&)
295 #else
296 #define STDEXEC_IMMOVABLE(_XP) _XP(_XP&&) = delete
297 #endif
298 
299 // BUG (gcc PR93711): copy elision fails when initializing a
300 // [[no_unique_address]] field from a function returning an object
301 // of class type by value
302 #if STDEXEC_GCC()
303 #define STDEXEC_IMMOVABLE_NO_UNIQUE_ADDRESS
304 #else
305 #define STDEXEC_IMMOVABLE_NO_UNIQUE_ADDRESS                                    \
306     STDEXEC_ATTRIBUTE((no_unique_address))
307 #endif
308 
309 #if STDEXEC_NVHPC()
310 #include <nv/target>
311 #define STDEXEC_TERMINATE()                                                    \
312     NV_IF_TARGET(NV_IS_HOST, (std::terminate();), (__trap();)) void()
313 #elif STDEXEC_CLANG() && STDEXEC_CUDA() && defined(__CUDA_ARCH__)
314 #define STDEXEC_TERMINATE()                                                    \
315     __trap();                                                                  \
316     __builtin_unreachable()
317 #else
318 #define STDEXEC_TERMINATE() std::terminate()
319 #endif
320 
321 #if STDEXEC_HAS_FEATURE(thread_sanitizer) || defined(__SANITIZE_THREAD__)
322 #define STDEXEC_TSAN(...) STDEXEC_HEAD_OR_TAIL(1, __VA_ARGS__)
323 #else
324 #define STDEXEC_TSAN(...) STDEXEC_HEAD_OR_NULL(0, __VA_ARGS__)
325 #endif
326 
327 // Before clang-16, clang did not like libstdc++'s ranges implementation
328 #if __has_include(<ranges>) && \
329   (defined(__cpp_lib_ranges) && __cpp_lib_ranges >= 201911L) && \
330   (!STDEXEC_CLANG() || __clang_major__ >= 16 || defined(_LIBCPP_VERSION))
331 #define STDEXEC_HAS_STD_RANGES() 1
332 #else
333 #define STDEXEC_HAS_STD_RANGES() 0
334 #endif
335 
336 #if __has_include(<memory_resource>) && \
337   (defined(__cpp_lib_memory_resource) && __cpp_lib_memory_resource >= 201603L)
338 #define STDEXEC_HAS_STD_MEMORY_RESOURCE() 1
339 #else
340 #define STDEXEC_HAS_STD_MEMORY_RESOURCE() 0
341 #endif
342 
343 #ifdef STDEXEC_ASSERT
344 #error                                                                         \
345     "Redefinition of STDEXEC_ASSERT is not permitted. Define STDEXEC_ASSERT_FN instead."
346 #endif
347 
348 #define STDEXEC_ASSERT(_XP)                                                    \
349     do                                                                         \
350     {                                                                          \
351         static_assert(noexcept(_XP));                                          \
352         STDEXEC_ASSERT_FN(_XP);                                                \
353     } while (false)
354 
355 #ifndef STDEXEC_ASSERT_FN
356 #define STDEXEC_ASSERT_FN assert
357 #endif
358 
359 #define STDEXEC_AUTO_RETURN(...)                                               \
360     noexcept(noexcept(__VA_ARGS__))->decltype(__VA_ARGS__)                     \
361     {                                                                          \
362         return __VA_ARGS__;                                                    \
363     }
364 
365 // GCC 13 implements lexical friendship, but it is incomplete. See
366 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111018
367 #if STDEXEC_CLANG() // || (STDEXEC_GCC() && __GNUC__ >= 13)
368 #define STDEXEC_FRIENDSHIP_IS_LEXICAL() 1
369 #else
370 #define STDEXEC_FRIENDSHIP_IS_LEXICAL() 0
371 #endif
372 
373 #if defined(__cpp_explicit_this_parameter) &&                                  \
374     (__cpp_explicit_this_parameter >= 202110)
375 #define STDEXEC_EXPLICIT_THIS(...) STDEXEC_HEAD_OR_TAIL(1, __VA_ARGS__)
376 #else
377 #define STDEXEC_EXPLICIT_THIS(...) STDEXEC_HEAD_OR_NULL(0, __VA_ARGS__)
378 #endif
379 
380 #if STDEXEC_EXPLICIT_THIS()
381 #define STDEXEC_DEFINE_EXPLICIT_THIS_MEMFN(...) __VA_ARGS__
382 #define STDEXEC_CALL_EXPLICIT_THIS_MEMFN(_OBJ, _NAME) (_OBJ)._NAME( STDEXEC_CALL_EXPLICIT_THIS_MEMFN_DETAIL
383 #define STDEXEC_CALL_EXPLICIT_THIS_MEMFN_DETAIL(...) __VA_ARGS__ )
384 #else
385 #define STDEXEC_DEFINE_EXPLICIT_THIS_MEMFN(...) static __VA_ARGS__(STDEXEC_FUN_ARGS
386 #define STDEXEC_CALL_EXPLICIT_THIS_MEMFN(_OBJ, _NAME) (_OBJ)._NAME((_OBJ) STDEXEC_CALL_EXPLICIT_THIS_MEMFN_DETAIL
387 #define STDEXEC_CALL_EXPLICIT_THIS_MEMFN_DETAIL(...) __VA_OPT__(, ) __VA_ARGS__)
388 #define STDEXEC_EAT_THIS_DETAIL_this
389 #define STDEXEC_FUN_ARGS(...) STDEXEC_CAT(STDEXEC_EAT_THIS_DETAIL_, __VA_ARGS__))
390 #endif
391 
392 // Configure extra type checking
393 #define STDEXEC_TYPE_CHECKING_ZERO() 0
394 #define STDEXEC_TYPE_CHECKING_ONE() 1
395 #define STDEXEC_TYPE_CHECKING_TWO() 2
396 
397 #define STDEXEC_PROBE_TYPE_CHECKING_ STDEXEC_TYPE_CHECKING_ONE
398 #define STDEXEC_PROBE_TYPE_CHECKING_0 STDEXEC_TYPE_CHECKING_ZERO
399 #define STDEXEC_PROBE_TYPE_CHECKING_1 STDEXEC_TYPE_CHECKING_ONE
400 #define STDEXEC_PROBE_TYPE_CHECKING_STDEXEC_ENABLE_EXTRA_TYPE_CHECKING         \
401     STDEXEC_TYPE_CHECKING_TWO
402 
403 #define STDEXEC_TYPE_CHECKING_WHICH3(...)                                      \
404     STDEXEC_PROBE_TYPE_CHECKING_##__VA_ARGS__
405 #define STDEXEC_TYPE_CHECKING_WHICH2(...)                                      \
406     STDEXEC_TYPE_CHECKING_WHICH3(__VA_ARGS__)
407 #define STDEXEC_TYPE_CHECKING_WHICH                                            \
408     STDEXEC_TYPE_CHECKING_WHICH2(STDEXEC_ENABLE_EXTRA_TYPE_CHECKING)
409 
410 #ifndef STDEXEC_ENABLE_EXTRA_TYPE_CHECKING
411 #define STDEXEC_ENABLE_EXTRA_TYPE_CHECKING() 0
412 #elif STDEXEC_TYPE_CHECKING_WHICH() == 2
413 // do nothing
414 #elif STDEXEC_TYPE_CHECKING_WHICH() == 0
415 #undef STDEXEC_ENABLE_EXTRA_TYPE_CHECKING
416 #define STDEXEC_ENABLE_EXTRA_TYPE_CHECKING() 0
417 #else
418 #undef STDEXEC_ENABLE_EXTRA_TYPE_CHECKING
419 #define STDEXEC_ENABLE_EXTRA_TYPE_CHECKING() 1
420 #endif
421 
422 namespace stdexec
423 {}
424