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 #if defined(_MSC_VER) && !defined(__clang__) 20 # error This library requires the use of C++20. Use /Zc:__cplusplus to enable __cplusplus conformance. 21 #else 22 #error This library requires the use of C++20. 23 #endif 24 #endif 25 26 #if defined(_MSC_VER) && !defined(__clang__) && \ 27 (!defined(_MSVC_TRADITIONAL) || _MSVC_TRADITIONAL) 28 # error This library requires the use of the new conforming preprocessor enabled by /Zc:preprocessor. 29 #endif 30 31 #if __has_include(<version>) 32 #include <version> 33 #else 34 #include <ciso646> // For stdlib feature-test macros when <version> is not available 35 #endif 36 37 #include <cassert> 38 #include <type_traits> 39 40 #define STDEXEC_STRINGIZE(_ARG) #_ARG 41 42 #define STDEXEC_CAT_(_XP, ...) _XP##__VA_ARGS__ 43 #define STDEXEC_CAT(_XP, ...) STDEXEC_CAT_(_XP, __VA_ARGS__) 44 45 #define STDEXEC_EXPAND(...) __VA_ARGS__ 46 #define STDEXEC_EVAL(_MACRO, ...) _MACRO(__VA_ARGS__) 47 #define STDEXEC_EAT(...) 48 49 #define STDEXEC_IIF(_XP, _YP, ...) \ 50 STDEXEC_IIF_EVAL(STDEXEC_CAT(STDEXEC_IIF_, _XP), _YP, __VA_ARGS__) 51 #define STDEXEC_IIF_0(_YP, ...) __VA_ARGS__ 52 #define STDEXEC_IIF_1(_YP, ...) _YP 53 #define STDEXEC_IIF_EVAL(_MACRO, ...) _MACRO(__VA_ARGS__) 54 55 #define STDEXEC_COMPL(_B) STDEXEC_COMPL_CAT(STDEXEC_COMPL_, _B) 56 #define STDEXEC_COMPL_0 1 57 #define STDEXEC_COMPL_1 0 58 #define STDEXEC_COMPL_CAT(_XP, ...) _XP##__VA_ARGS__ 59 60 #define STDEXEC_COUNT(...) \ 61 STDEXEC_EXPAND(STDEXEC_COUNT_(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)) 62 #define STDEXEC_COUNT_(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _NP, ...) _NP 63 64 #define STDEXEC_CHECK(...) STDEXEC_EXPAND(STDEXEC_CHECK_(__VA_ARGS__, 0, )) 65 #define STDEXEC_CHECK_(_XP, _NP, ...) _NP 66 #define STDEXEC_PROBE(...) STDEXEC_PROBE_(__VA_ARGS__, 1) 67 #define STDEXEC_PROBE_(_XP, _NP, ...) _XP, _NP, 68 69 #define STDEXEC_NOT(_XP) STDEXEC_CHECK(STDEXEC_CAT(STDEXEC_NOT_, _XP)) 70 #define STDEXEC_NOT_0 STDEXEC_PROBE(~, 1) 71 72 #define STDEXEC_BOOL(_XP) STDEXEC_COMPL(STDEXEC_NOT(_XP)) 73 #define STDEXEC_IF(_XP, _YP, ...) \ 74 STDEXEC_IIF(STDEXEC_BOOL(_XP), _YP, __VA_ARGS__) 75 76 #define STDEXEC_WHEN(_XP, ...) \ 77 STDEXEC_IF(_XP, STDEXEC_EXPAND, STDEXEC_EAT)(__VA_ARGS__) 78 79 //////////////////////////////////////////////////////////////////////////////// 80 // STDEXEC_FOR_EACH 81 // Inspired by "Recursive macros with C++20 __VA_OPT__", by David Mazières 82 // https://www.scs.stanford.edu/~dm/blog/va-opt.html 83 #define STDEXEC_EXPAND_R(...) \ 84 STDEXEC_EXPAND_R1( \ 85 STDEXEC_EXPAND_R1(STDEXEC_EXPAND_R1(STDEXEC_EXPAND_R1(__VA_ARGS__)))) \ 86 /**/ 87 #define STDEXEC_EXPAND_R1(...) \ 88 STDEXEC_EXPAND_R2( \ 89 STDEXEC_EXPAND_R2(STDEXEC_EXPAND_R2(STDEXEC_EXPAND_R2(__VA_ARGS__)))) \ 90 /**/ 91 #define STDEXEC_EXPAND_R2(...) \ 92 STDEXEC_EXPAND_R3( \ 93 STDEXEC_EXPAND_R3(STDEXEC_EXPAND_R3(STDEXEC_EXPAND_R3(__VA_ARGS__)))) \ 94 /**/ 95 #define STDEXEC_EXPAND_R3(...) \ 96 STDEXEC_EXPAND( \ 97 STDEXEC_EXPAND(STDEXEC_EXPAND(STDEXEC_EXPAND(__VA_ARGS__)))) \ 98 /**/ 99 100 #define STDEXEC_PARENS () 101 #define STDEXEC_FOR_EACH(_MACRO, ...) \ 102 __VA_OPT__(STDEXEC_EXPAND_R(STDEXEC_FOR_EACH_HELPER(_MACRO, __VA_ARGS__))) \ 103 /**/ 104 #define STDEXEC_FOR_EACH_HELPER(_MACRO, _A1, ...) \ 105 _MACRO(_A1) \ 106 __VA_OPT__(STDEXEC_FOR_EACH_AGAIN STDEXEC_PARENS(_MACRO, __VA_ARGS__)) /**/ 107 #define STDEXEC_FOR_EACH_AGAIN() STDEXEC_FOR_EACH_HELPER 108 //////////////////////////////////////////////////////////////////////////////////////////////////// 109 110 #define STDEXEC_FRONT(...) __VA_OPT__(STDEXEC_FRONT_HELPER(__VA_ARGS__)) 111 #define STDEXEC_FRONT_HELPER(_A1, ...) _A1 112 #define STDEXEC_BACK(...) \ 113 __VA_OPT__(STDEXEC_EXPAND_R(STDEXEC_BACK_HELPER(__VA_ARGS__))) 114 #define STDEXEC_BACK_HELPER(_A1, ...) \ 115 STDEXEC_FRONT(__VA_OPT__(, ) _A1, ) \ 116 __VA_OPT__(STDEXEC_BACK_AGAIN STDEXEC_PARENS(__VA_ARGS__)) 117 #define STDEXEC_BACK_AGAIN() STDEXEC_BACK_HELPER 118 119 // If tail is non-empty, expand to the tail. Otherwise, expand to the head 120 #define STDEXEC_HEAD_OR_TAIL(_XP, ...) \ 121 STDEXEC_EXPAND __VA_OPT__((__VA_ARGS__)STDEXEC_EAT)(_XP) 122 123 // If tail is non-empty, expand to nothing. Otherwise, expand to the head 124 #define STDEXEC_HEAD_OR_NULL(_XP, ...) \ 125 STDEXEC_EXPAND __VA_OPT__(() STDEXEC_EAT)(_XP) 126 127 // When used with no arguments, these macros expand to 1 if the current 128 // compiler corresponds to the macro name; 0, otherwise. When used with 129 // arguments, they expand to the arguments if if the current compiler 130 // corresponds to the macro name; nothing, otherwise. 131 #if defined(__NVCC__) 132 #define STDEXEC_NVCC(...) STDEXEC_HEAD_OR_TAIL(1, __VA_ARGS__) 133 #elif defined(__EDG__) 134 #define STDEXEC_EDG(...) STDEXEC_HEAD_OR_TAIL(1, __VA_ARGS__) 135 #if defined(__NVCOMPILER) 136 #define STDEXEC_NVHPC(...) STDEXEC_HEAD_OR_TAIL(1, __VA_ARGS__) 137 #endif 138 #if defined(__INTELLISENSE__) 139 #define STDEXEC_INTELLISENSE(...) STDEXEC_HEAD_OR_TAIL(1, __VA_ARGS__) 140 #define STDEXEC_MSVC_HEADERS(...) STDEXEC_HEAD_OR_TAIL(1, __VA_ARGS__) 141 #endif 142 #elif defined(__clang__) 143 #define STDEXEC_CLANG(...) STDEXEC_HEAD_OR_TAIL(1, __VA_ARGS__) 144 #if defined(_MSC_VER) 145 #define STDEXEC_CLANG_CL(...) STDEXEC_HEAD_OR_TAIL(1, __VA_ARGS__) 146 #endif 147 #if defined(__apple_build_version__) 148 #define STDEXEC_APPLE_CLANG(...) STDEXEC_HEAD_OR_TAIL(1, __VA_ARGS__) 149 #endif 150 #elif defined(__GNUC__) 151 #define STDEXEC_GCC(...) STDEXEC_HEAD_OR_TAIL(1, __VA_ARGS__) 152 #elif defined(_MSC_VER) 153 #define STDEXEC_MSVC(...) STDEXEC_HEAD_OR_TAIL(1, __VA_ARGS__) 154 #define STDEXEC_MSVC_HEADERS(...) STDEXEC_HEAD_OR_TAIL(1, __VA_ARGS__) 155 #endif 156 157 #ifndef STDEXEC_NVCC 158 #define STDEXEC_NVCC(...) STDEXEC_HEAD_OR_NULL(0, __VA_ARGS__) 159 #endif 160 #ifndef STDEXEC_NVHPC 161 #define STDEXEC_NVHPC(...) STDEXEC_HEAD_OR_NULL(0, __VA_ARGS__) 162 #endif 163 #ifndef STDEXEC_EDG 164 #define STDEXEC_EDG(...) STDEXEC_HEAD_OR_NULL(0, __VA_ARGS__) 165 #endif 166 #ifndef STDEXEC_CLANG 167 #define STDEXEC_CLANG(...) STDEXEC_HEAD_OR_NULL(0, __VA_ARGS__) 168 #endif 169 #ifndef STDEXEC_CLANG_CL 170 #define STDEXEC_CLANG_CL(...) STDEXEC_HEAD_OR_NULL(0, __VA_ARGS__) 171 #endif 172 #ifndef STDEXEC_APPLE_CLANG 173 #define STDEXEC_APPLE_CLANG(...) STDEXEC_HEAD_OR_NULL(0, __VA_ARGS__) 174 #endif 175 #ifndef STDEXEC_GCC 176 #define STDEXEC_GCC(...) STDEXEC_HEAD_OR_NULL(0, __VA_ARGS__) 177 #endif 178 #ifndef STDEXEC_MSVC 179 #define STDEXEC_MSVC(...) STDEXEC_HEAD_OR_NULL(0, __VA_ARGS__) 180 #endif 181 #ifndef STDEXEC_MSVC_HEADERS 182 #define STDEXEC_MSVC_HEADERS(...) STDEXEC_HEAD_OR_NULL(0, __VA_ARGS__) 183 #endif 184 #ifndef STDEXEC_INTELLISENSE 185 #define STDEXEC_INTELLISENSE(...) STDEXEC_HEAD_OR_NULL(0, __VA_ARGS__) 186 #endif 187 188 #if STDEXEC_NVHPC() 189 #define STDEXEC_NVHPC_VERSION() \ 190 (__NVCOMPILER_MAJOR__ * 100 + __NVCOMPILER_MINOR__) 191 #endif 192 193 //////////////////////////////////////////////////////////////////////////////////////////////////// 194 #ifdef __CUDACC__ 195 #define STDEXEC_CUDA(...) STDEXEC_HEAD_OR_TAIL(1, __VA_ARGS__) 196 #else 197 #define STDEXEC_CUDA(...) STDEXEC_HEAD_OR_NULL(0, __VA_ARGS__) 198 #endif 199 200 //////////////////////////////////////////////////////////////////////////////////////////////////// 201 #if __cpp_impl_coroutine >= 201902 && __cpp_lib_coroutine >= 201902 202 #include <coroutine> 203 #define STDEXEC_STD_NO_COROUTINES() 0 204 namespace __coro = std; 205 #elif defined(__cpp_coroutines) && __has_include(<experimental/coroutine>) 206 #include <experimental/coroutine> 207 #define STDEXEC_STD_NO_COROUTINES() 0 208 namespace __coro = std::experimental; 209 #else 210 #define STDEXEC_STD_NO_COROUTINES() 1 211 #endif 212 213 //////////////////////////////////////////////////////////////////////////////////////////////////// 214 // For portably declaring attributes on functions and types 215 // Usage: 216 // 217 // STDEXEC_ATTRIBUTE((attr1, attr2, ...)) 218 // void foo() { ... } 219 #define STDEXEC_ATTRIBUTE(_XP) \ 220 STDEXEC_FOR_EACH(STDEXEC_ATTR, STDEXEC_EXPAND _XP) 221 #define STDEXEC_ATTR(_ATTR) \ 222 STDEXEC_CAT(STDEXEC_ATTR_WHICH_, \ 223 STDEXEC_CHECK(STDEXEC_CAT(STDEXEC_ATTR_, _ATTR))) \ 224 (_ATTR) 225 226 // unknown attributes are treated like C++-style attributes 227 #define STDEXEC_ATTR_WHICH_0(_ATTR) [[_ATTR]] 228 229 // custom handling for specific attribute types 230 #ifdef __CUDACC__ 231 #define STDEXEC_ATTR_WHICH_1(_ATTR) __host__ 232 #else 233 #define STDEXEC_ATTR_WHICH_1(_ATTR) 234 #endif 235 #define STDEXEC_ATTR_host STDEXEC_PROBE(~, 1) 236 #define STDEXEC_ATTR___host__ STDEXEC_PROBE(~, 1) 237 238 #ifdef __CUDACC__ 239 #define STDEXEC_ATTR_WHICH_2(_ATTR) __device__ 240 #else 241 #define STDEXEC_ATTR_WHICH_2(_ATTR) 242 #endif 243 #define STDEXEC_ATTR_device STDEXEC_PROBE(~, 2) 244 #define STDEXEC_ATTR___device__ STDEXEC_PROBE(~, 2) 245 246 #if STDEXEC_NVHPC() 247 // NVBUG #4067067: NVHPC does not fully support [[no_unique_address]] 248 #define STDEXEC_ATTR_WHICH_3(_ATTR) /*nothing*/ 249 #elif STDEXEC_MSVC() 250 // MSVCBUG 251 // https://developercommunity.visualstudio.com/t/Incorrect-codegen-when-using-msvc::no_/10452874 252 #define STDEXEC_ATTR_WHICH_3(_ATTR) // [[msvc::no_unique_address]] 253 #elif STDEXEC_CLANG_CL() 254 // clang-cl does not support: https://reviews.llvm.org/D110485 255 #define STDEXEC_ATTR_WHICH_3(_ATTR) // [[msvc::no_unique_address]] 256 #else 257 #define STDEXEC_ATTR_WHICH_3(_ATTR) [[no_unique_address]] 258 #endif 259 #define STDEXEC_ATTR_no_unique_address STDEXEC_PROBE(~, 3) 260 261 #if STDEXEC_MSVC() 262 #define STDEXEC_ATTR_WHICH_4(_ATTR) __forceinline 263 #elif STDEXEC_CLANG() 264 #define STDEXEC_ATTR_WHICH_4(_ATTR) \ 265 __attribute__((__always_inline__, __artificial__, __nodebug__)) inline 266 #elif defined(__GNUC__) 267 #define STDEXEC_ATTR_WHICH_4(_ATTR) \ 268 __attribute__((__always_inline__, __artificial__)) inline 269 #else 270 #define STDEXEC_ATTR_WHICH_4(_ATTR) /*nothing*/ 271 #endif 272 #define STDEXEC_ATTR_always_inline STDEXEC_PROBE(~, 4) 273 274 #if STDEXEC_CLANG() || STDEXEC_GCC() 275 #define STDEXEC_ATTR_WHICH_5(_ATTR) __attribute__((__weak__)) 276 #else 277 #define STDEXEC_ATTR_WHICH_5(_ATTR) /*nothing*/ 278 #endif 279 #define STDEXEC_ATTR_weak STDEXEC_PROBE(~, 5) 280 #define STDEXEC_ATTR___weak__ STDEXEC_PROBE(~, 5) 281 282 //////////////////////////////////////////////////////////////////////////////////////////////////// 283 // warning push/pop portability macros 284 #if STDEXEC_NVCC() 285 #define STDEXEC_PRAGMA_PUSH() _Pragma("nv_diagnostic push") 286 #define STDEXEC_PRAGMA_POP() _Pragma("nv_diagnostic pop") 287 #define STDEXEC_PRAGMA_IGNORE_EDG(...) \ 288 _Pragma(STDEXEC_STRINGIZE(nv_diag_suppress __VA_ARGS__)) 289 #elif STDEXEC_EDG() 290 #define STDEXEC_PRAGMA_PUSH() \ 291 _Pragma("diagnostic push") STDEXEC_PRAGMA_IGNORE_EDG(invalid_error_number) 292 #define STDEXEC_PRAGMA_POP() _Pragma("diagnostic pop") 293 #define STDEXEC_PRAGMA_IGNORE_EDG(...) \ 294 _Pragma(STDEXEC_STRINGIZE(diag_suppress __VA_ARGS__)) 295 #elif STDEXEC_CLANG() || STDEXEC_GCC() 296 #define STDEXEC_PRAGMA_PUSH() \ 297 _Pragma("GCC diagnostic push") STDEXEC_PRAGMA_IGNORE_GNU("-Wpragmas") \ 298 STDEXEC_PRAGMA_IGNORE_GNU("-Wunknown-pragmas") \ 299 STDEXEC_PRAGMA_IGNORE_GNU("-Wunknown-warning-option") \ 300 STDEXEC_PRAGMA_IGNORE_GNU("-Wunknown-attributes") \ 301 STDEXEC_PRAGMA_IGNORE_GNU("-Wattributes") 302 #define STDEXEC_PRAGMA_POP() _Pragma("GCC diagnostic pop") 303 #define STDEXEC_PRAGMA_IGNORE_GNU(...) \ 304 _Pragma(STDEXEC_STRINGIZE(GCC diagnostic ignored __VA_ARGS__)) 305 #elif STDEXEC_MSVC() 306 #define STDEXEC_PRAGMA_PUSH() __pragma(warning(push)) 307 #define STDEXEC_PRAGMA_POP() __pragma(warning(pop)) 308 #define STDEXEC_PRAGMA_IGNORE_MSVC(...) __pragma(warning(disable : __VA_ARGS__)) 309 #else 310 #define STDEXEC_PRAGMA_PUSH() 311 #define STDEXEC_PRAGMA_POP() 312 #endif 313 314 #ifndef STDEXEC_PRAGMA_IGNORE_GNU 315 #define STDEXEC_PRAGMA_IGNORE_GNU(...) 316 #endif 317 #ifndef STDEXEC_PRAGMA_IGNORE_EDG 318 #define STDEXEC_PRAGMA_IGNORE_EDG(...) 319 #endif 320 #ifndef STDEXEC_PRAGMA_IGNORE_MSVC 321 #define STDEXEC_PRAGMA_IGNORE_MSVC(...) 322 #endif 323 324 #if !STDEXEC_MSVC() && defined(__has_builtin) 325 #define STDEXEC_HAS_BUILTIN __has_builtin 326 #else 327 #define STDEXEC_HAS_BUILTIN(...) 0 328 #endif 329 330 #if !STDEXEC_MSVC() && defined(__has_feature) 331 #define STDEXEC_HAS_FEATURE __has_feature 332 #else 333 #define STDEXEC_HAS_FEATURE(...) 0 334 #endif 335 336 #if STDEXEC_HAS_BUILTIN(__is_trivially_copyable) || STDEXEC_MSVC() 337 #define STDEXEC_IS_TRIVIALLY_COPYABLE(...) __is_trivially_copyable(__VA_ARGS__) 338 #else 339 #define STDEXEC_IS_TRIVIALLY_COPYABLE(...) \ 340 std::is_trivially_copyable_v<__VA_ARGS__> 341 #endif 342 343 #if STDEXEC_HAS_BUILTIN(__is_base_of) || (_MSC_VER >= 1914) 344 #define STDEXEC_IS_BASE_OF(...) __is_base_of(__VA_ARGS__) 345 #else 346 #define STDEXEC_IS_BASE_OF(...) std::is_base_of_v<__VA_ARGS__> 347 #endif 348 349 #if STDEXEC_HAS_BUILTIN(__is_convertible_to) || STDEXEC_MSVC() 350 #define STDEXEC_IS_CONVERTIBLE_TO(...) __is_convertible_to(__VA_ARGS__) 351 #elif STDEXEC_HAS_BUILTIN(__is_convertible) 352 #define STDEXEC_IS_CONVERTIBLE_TO(...) __is_convertible(__VA_ARGS__) 353 #else 354 #define STDEXEC_IS_CONVERTIBLE_TO(...) std::is_convertible_v<__VA_ARGS__> 355 #endif 356 357 #if STDEXEC_HAS_BUILTIN(__is_const) 358 #define STDEXEC_IS_CONST(...) __is_const(__VA_ARGS__) 359 #else 360 #define STDEXEC_IS_CONST(...) stdexec::__is_const_<__VA_ARGS__> 361 #endif 362 363 #if STDEXEC_HAS_BUILTIN(__is_same) 364 #define STDEXEC_IS_SAME(...) __is_same(__VA_ARGS__) 365 #elif STDEXEC_HAS_BUILTIN(__is_same_as) 366 #define STDEXEC_IS_SAME(...) __is_same_as(__VA_ARGS__) 367 #elif STDEXEC_MSVC() 368 // msvc replaces std::is_same_v with a compile-time constant 369 #define STDEXEC_IS_SAME(...) std::is_same_v<__VA_ARGS__> 370 #else 371 #define STDEXEC_IS_SAME(...) stdexec::__same_as_v<__VA_ARGS__> 372 #endif 373 374 #if STDEXEC_HAS_BUILTIN(__is_constructible) || STDEXEC_MSVC() 375 #define STDEXEC_IS_CONSTRUCTIBLE(...) __is_constructible(__VA_ARGS__) 376 #else 377 #define STDEXEC_IS_CONSTRUCTIBLE(...) std::is_constructible_v<__VA_ARGS__> 378 #endif 379 380 #if STDEXEC_HAS_BUILTIN(__is_nothrow_constructible) || STDEXEC_MSVC() 381 #define STDEXEC_IS_NOTHROW_CONSTRUCTIBLE(...) \ 382 __is_nothrow_constructible(__VA_ARGS__) 383 #else 384 #define STDEXEC_IS_NOTHROW_CONSTRUCTIBLE(...) \ 385 std::is_nothrow_constructible_v<__VA_ARGS__> 386 #endif 387 388 #if STDEXEC_HAS_BUILTIN(__is_trivially_constructible) || STDEXEC_MSVC() 389 #define STDEXEC_IS_TRIVIALLY_CONSTRUCTIBLE(...) \ 390 __is_trivially_constructible(__VA_ARGS__) 391 #else 392 #define STDEXEC_IS_TRIVIALLY_CONSTRUCTIBLE(...) \ 393 std::is_trivially_constructible_v<__VA_ARGS__> 394 #endif 395 396 #if STDEXEC_HAS_BUILTIN(__is_empty) || STDEXEC_MSVC() 397 #define STDEXEC_IS_EMPTY(...) __is_empty(__VA_ARGS__) 398 #else 399 #define STDEXEC_IS_EMPTY(...) std::is_empty_v<__VA_ARGS__> 400 #endif 401 402 #if STDEXEC_HAS_BUILTIN(__remove_reference) 403 namespace stdexec 404 { 405 template <class Ty> 406 using _remove_reference_t = __remove_reference(Ty); 407 } // namespace stdexec 408 409 #define STDEXEC_REMOVE_REFERENCE(...) stdexec::_remove_reference_t<__VA_ARGS__> 410 #elif STDEXEC_HAS_BUILTIN(__remove_reference_t) 411 namespace stdexec 412 { 413 template <class Ty> 414 using _remove_reference_t = __remove_reference_t(Ty); 415 } // namespace stdexec 416 417 #define STDEXEC_REMOVE_REFERENCE(...) stdexec::_remove_reference_t<__VA_ARGS__> 418 #else 419 #define STDEXEC_REMOVE_REFERENCE(...) ::std::remove_reference_t<__VA_ARGS__> 420 #endif 421 422 namespace stdexec 423 { 424 template <class _Ap, class _Bp> 425 inline constexpr bool __same_as_v = false; 426 427 template <class _Ap> 428 inline constexpr bool __same_as_v<_Ap, _Ap> = true; 429 } // namespace stdexec 430 431 #if defined(__cpp_lib_unreachable) && __cpp_lib_unreachable >= 202202L 432 #define STDEXEC_UNREACHABLE() std::unreachable() 433 #elif STDEXEC_HAS_BUILTIN(__builtin_unreachable) 434 #define STDEXEC_UNREACHABLE() __builtin_unreachable() 435 #elif STDEXEC_MSVC() 436 #define STDEXEC_UNREACHABLE(...) __assume(false) 437 #else 438 #define STDEXEC_UNREACHABLE(...) std::terminate() 439 #endif 440 441 // Before gcc-12, gcc really didn't like tuples or variants of immovable types 442 #if STDEXEC_GCC() && (__GNUC__ < 12) 443 #define STDEXEC_IMMOVABLE(_XP) _XP(_XP&&) 444 #else 445 #define STDEXEC_IMMOVABLE(_XP) _XP(_XP&&) = delete 446 #endif 447 448 // BUG (gcc PR93711): copy elision fails when initializing a 449 // [[no_unique_address]] field from a function returning an object 450 // of class type by value 451 #if STDEXEC_GCC() 452 #define STDEXEC_IMMOVABLE_NO_UNIQUE_ADDRESS 453 #else 454 #define STDEXEC_IMMOVABLE_NO_UNIQUE_ADDRESS \ 455 STDEXEC_ATTRIBUTE((no_unique_address)) 456 #endif 457 458 #if STDEXEC_NVHPC() 459 #include <nv/target> 460 #define STDEXEC_TERMINATE() \ 461 NV_IF_TARGET(NV_IS_HOST, (std::terminate();), (__trap();)) void() 462 #elif STDEXEC_CLANG() && STDEXEC_CUDA() && defined(__CUDA_ARCH__) 463 #define STDEXEC_TERMINATE() \ 464 __trap(); \ 465 __builtin_unreachable() 466 #else 467 #define STDEXEC_TERMINATE() std::terminate() 468 #endif 469 470 #if STDEXEC_HAS_FEATURE(thread_sanitizer) || defined(__SANITIZE_THREAD__) 471 #define STDEXEC_TSAN(...) STDEXEC_HEAD_OR_TAIL(1, __VA_ARGS__) 472 #else 473 #define STDEXEC_TSAN(...) STDEXEC_HEAD_OR_NULL(0, __VA_ARGS__) 474 #endif 475 476 // Before clang-16, clang did not like libstdc++'s ranges implementation 477 #if __has_include(<ranges>) && \ 478 (defined(__cpp_lib_ranges) && __cpp_lib_ranges >= 201911L) && \ 479 (!STDEXEC_CLANG() || __clang_major__ >= 16 || defined(_LIBCPP_VERSION)) 480 #define STDEXEC_HAS_STD_RANGES() 1 481 #else 482 #define STDEXEC_HAS_STD_RANGES() 0 483 #endif 484 485 #if __has_include(<memory_resource>) && \ 486 (defined(__cpp_lib_memory_resource) && __cpp_lib_memory_resource >= 201603L) 487 #define STDEXEC_HAS_STD_MEMORY_RESOURCE() 1 488 #else 489 #define STDEXEC_HAS_STD_MEMORY_RESOURCE() 0 490 #endif 491 492 #ifdef STDEXEC_ASSERT 493 #error \ 494 "Redefinition of STDEXEC_ASSERT is not permitted. Define STDEXEC_ASSERT_FN instead." 495 #endif 496 497 #define STDEXEC_ASSERT(_XP) \ 498 do \ 499 { \ 500 static_assert(noexcept(_XP)); \ 501 STDEXEC_ASSERT_FN(_XP); \ 502 } while (false) 503 504 #ifndef STDEXEC_ASSERT_FN 505 #define STDEXEC_ASSERT_FN assert 506 #endif 507 508 #define STDEXEC_AUTO_RETURN(...) \ 509 noexcept(noexcept(__VA_ARGS__))->decltype(__VA_ARGS__) \ 510 { \ 511 return __VA_ARGS__; \ 512 } 513 514 // GCC 13 implements lexical friendship, but it is incomplete. See 515 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111018 516 #if STDEXEC_CLANG() // || (STDEXEC_GCC() && __GNUC__ >= 13) 517 #define STDEXEC_FRIENDSHIP_IS_LEXICAL() 1 518 #else 519 #define STDEXEC_FRIENDSHIP_IS_LEXICAL() 0 520 #endif 521 522 #if defined(__cpp_explicit_this_parameter) && \ 523 (__cpp_explicit_this_parameter >= 202110) 524 #define STDEXEC_EXPLICIT_THIS(...) STDEXEC_HEAD_OR_TAIL(1, __VA_ARGS__) 525 #else 526 #define STDEXEC_EXPLICIT_THIS(...) STDEXEC_HEAD_OR_NULL(0, __VA_ARGS__) 527 #endif 528 529 // Configure extra type checking 530 #define STDEXEC_TYPE_CHECKING_ZERO() 0 531 #define STDEXEC_TYPE_CHECKING_ONE() 1 532 #define STDEXEC_TYPE_CHECKING_TWO() 2 533 534 #define STDEXEC_PROBE_TYPE_CHECKING_ STDEXEC_TYPE_CHECKING_ONE 535 #define STDEXEC_PROBE_TYPE_CHECKING_0 STDEXEC_TYPE_CHECKING_ZERO 536 #define STDEXEC_PROBE_TYPE_CHECKING_1 STDEXEC_TYPE_CHECKING_ONE 537 #define STDEXEC_PROBE_TYPE_CHECKING_STDEXEC_ENABLE_EXTRA_TYPE_CHECKING \ 538 STDEXEC_TYPE_CHECKING_TWO 539 540 #define STDEXEC_TYPE_CHECKING_WHICH3(...) \ 541 STDEXEC_PROBE_TYPE_CHECKING_##__VA_ARGS__ 542 #define STDEXEC_TYPE_CHECKING_WHICH2(...) \ 543 STDEXEC_TYPE_CHECKING_WHICH3(__VA_ARGS__) 544 #define STDEXEC_TYPE_CHECKING_WHICH \ 545 STDEXEC_TYPE_CHECKING_WHICH2(STDEXEC_ENABLE_EXTRA_TYPE_CHECKING) 546 547 #ifndef STDEXEC_ENABLE_EXTRA_TYPE_CHECKING 548 #define STDEXEC_ENABLE_EXTRA_TYPE_CHECKING() 0 549 #elif STDEXEC_TYPE_CHECKING_WHICH() == 2 550 // do nothing 551 #elif STDEXEC_TYPE_CHECKING_WHICH() == 0 552 #undef STDEXEC_ENABLE_EXTRA_TYPE_CHECKING 553 #define STDEXEC_ENABLE_EXTRA_TYPE_CHECKING() 0 554 #else 555 #undef STDEXEC_ENABLE_EXTRA_TYPE_CHECKING 556 #define STDEXEC_ENABLE_EXTRA_TYPE_CHECKING() 1 557 #endif 558 559 namespace stdexec 560 {} 561