File indexing completed on 2025-12-15 10:11:16
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019 #ifndef CPP_CONCEPTS_HPP
0020 #define CPP_CONCEPTS_HPP
0021
0022
0023
0024 #include <initializer_list>
0025 #include <utility>
0026 #include <type_traits>
0027 #include <concepts/swap.hpp>
0028 #include <concepts/type_traits.hpp>
0029
0030
0031
0032
0033 #if defined(__clang__) && __cplusplus <= 201703L
0034 #define CPP_PP_IGNORE_CXX2A_COMPAT_BEGIN \
0035 CPP_DIAGNOSTIC_PUSH \
0036 CPP_DIAGNOSTIC_IGNORE_CPP2A_COMPAT
0037
0038 #define CPP_PP_IGNORE_CXX2A_COMPAT_END \
0039 CPP_DIAGNOSTIC_POP
0040
0041 #else
0042 #define CPP_PP_IGNORE_CXX2A_COMPAT_BEGIN
0043 #define CPP_PP_IGNORE_CXX2A_COMPAT_END
0044 #endif
0045
0046 #if defined(_MSC_VER) && !defined(__clang__)
0047 #define CPP_WORKAROUND_MSVC_779763
0048 #define CPP_WORKAROUND_MSVC_784772
0049 #endif
0050
0051 #if !defined(CPP_CXX_CONCEPTS)
0052 #ifdef CPP_DOXYGEN_INVOKED
0053 #define CPP_CXX_CONCEPTS 201800L
0054 #elif defined(__cpp_concepts) && __cpp_concepts > 0
0055
0056 #if !defined(__GNUC__) || defined(__clang__) || __GNUC__ >= 7
0057 #define CPP_CXX_CONCEPTS __cpp_concepts
0058 #else
0059 #define CPP_CXX_CONCEPTS 0L
0060 #endif
0061 #else
0062 #define CPP_CXX_CONCEPTS 0L
0063 #endif
0064 #endif
0065
0066 #define CPP_PP_CAT_(X, ...) X ## __VA_ARGS__
0067 #define CPP_PP_CAT(X, ...) CPP_PP_CAT_(X, __VA_ARGS__)
0068
0069 #define CPP_PP_EVAL_(X, ARGS) X ARGS
0070 #define CPP_PP_EVAL(X, ...) CPP_PP_EVAL_(X, (__VA_ARGS__))
0071
0072 #define CPP_PP_EVAL2_(X, ARGS) X ARGS
0073 #define CPP_PP_EVAL2(X, ...) CPP_PP_EVAL2_(X, (__VA_ARGS__))
0074
0075 #define CPP_PP_EXPAND(...) __VA_ARGS__
0076 #define CPP_PP_EAT(...)
0077
0078 #define CPP_PP_FIRST(LIST) CPP_PP_FIRST_ LIST
0079 #define CPP_PP_FIRST_(...) __VA_ARGS__ CPP_PP_EAT
0080
0081 #define CPP_PP_SECOND(LIST) CPP_PP_SECOND_ LIST
0082 #define CPP_PP_SECOND_(...) CPP_PP_EXPAND
0083
0084 #define CPP_PP_CHECK(...) CPP_PP_EXPAND(CPP_PP_CHECK_N(__VA_ARGS__, 0,))
0085 #define CPP_PP_CHECK_N(x, n, ...) n
0086 #define CPP_PP_PROBE(x) x, 1,
0087 #define CPP_PP_PROBE_N(x, n) x, n,
0088
0089 #define CPP_PP_IS_PAREN(x) CPP_PP_CHECK(CPP_PP_IS_PAREN_PROBE x)
0090 #define CPP_PP_IS_PAREN_PROBE(...) CPP_PP_PROBE(~)
0091
0092
0093 #ifndef CPP_CXX_VA_OPT
0094 #if __cplusplus > 201703L
0095 #define CPP_CXX_VA_OPT_(...) CPP_PP_CHECK(__VA_OPT__(,) 1)
0096 #define CPP_CXX_VA_OPT CPP_CXX_VA_OPT_(~)
0097 #else
0098 #define CPP_CXX_VA_OPT 0
0099 #endif
0100 #endif
0101
0102
0103
0104 #define CPP_PP_COUNT(...) \
0105 CPP_PP_EXPAND(CPP_PP_COUNT_(__VA_ARGS__, \
0106 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, \
0107 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, \
0108 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, \
0109 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, \
0110 10, 9, 8, 7, 6, 5, 4, 3, 2, 1,))
0111
0112 #define CPP_PP_COUNT_( \
0113 _01, _02, _03, _04, _05, _06, _07, _08, _09, _10, \
0114 _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \
0115 _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \
0116 _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \
0117 _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, N, ...) \
0118 N
0119
0120 #define CPP_PP_IIF(BIT) CPP_PP_CAT_(CPP_PP_IIF_, BIT)
0121 #define CPP_PP_IIF_0(TRUE, ...) __VA_ARGS__
0122 #define CPP_PP_IIF_1(TRUE, ...) TRUE
0123
0124 #define CPP_PP_LPAREN (
0125 #define CPP_PP_RPAREN )
0126
0127 #define CPP_PP_NOT(BIT) CPP_PP_CAT_(CPP_PP_NOT_, BIT)
0128 #define CPP_PP_NOT_0 1
0129 #define CPP_PP_NOT_1 0
0130
0131 #define CPP_PP_EMPTY()
0132 #define CPP_PP_COMMA() ,
0133 #define CPP_PP_LBRACE() {
0134 #define CPP_PP_RBRACE() }
0135 #define CPP_PP_COMMA_IIF(X) \
0136 CPP_PP_IIF(X)(CPP_PP_EMPTY, CPP_PP_COMMA)()
0137
0138 #define CPP_PP_FOR_EACH(M, ...) \
0139 CPP_PP_FOR_EACH_N(CPP_PP_COUNT(__VA_ARGS__), M, __VA_ARGS__)
0140 #define CPP_PP_FOR_EACH_N(N, M, ...) \
0141 CPP_PP_CAT(CPP_PP_FOR_EACH_, N)(M, __VA_ARGS__)
0142 #define CPP_PP_FOR_EACH_1(M, _1) \
0143 M(_1)
0144 #define CPP_PP_FOR_EACH_2(M, _1, _2) \
0145 M(_1), M(_2)
0146 #define CPP_PP_FOR_EACH_3(M, _1, _2, _3) \
0147 M(_1), M(_2), M(_3)
0148 #define CPP_PP_FOR_EACH_4(M, _1, _2, _3, _4) \
0149 M(_1), M(_2), M(_3), M(_4)
0150 #define CPP_PP_FOR_EACH_5(M, _1, _2, _3, _4, _5) \
0151 M(_1), M(_2), M(_3), M(_4), M(_5)
0152 #define CPP_PP_FOR_EACH_6(M, _1, _2, _3, _4, _5, _6) \
0153 M(_1), M(_2), M(_3), M(_4), M(_5), M(_6)
0154 #define CPP_PP_FOR_EACH_7(M, _1, _2, _3, _4, _5, _6, _7) \
0155 M(_1), M(_2), M(_3), M(_4), M(_5), M(_6), M(_7)
0156 #define CPP_PP_FOR_EACH_8(M, _1, _2, _3, _4, _5, _6, _7, _8) \
0157 M(_1), M(_2), M(_3), M(_4), M(_5), M(_6), M(_7), M(_8)
0158
0159 #define CPP_PP_PROBE_EMPTY_PROBE_CPP_PP_PROBE_EMPTY \
0160 CPP_PP_PROBE(~)
0161
0162 #define CPP_PP_PROBE_EMPTY()
0163 #define CPP_PP_IS_NOT_EMPTY(...) \
0164 CPP_PP_EVAL( \
0165 CPP_PP_CHECK, \
0166 CPP_PP_CAT( \
0167 CPP_PP_PROBE_EMPTY_PROBE_, \
0168 CPP_PP_PROBE_EMPTY __VA_ARGS__ ()))
0169
0170 #if defined(_MSC_VER) && !defined(__clang__) && (__cplusplus <= 201703L)
0171 #define CPP_BOOL(...) ::meta::bool_<__VA_ARGS__>::value
0172 #define CPP_TRUE_FN \
0173 !::concepts::detail::instance_< \
0174 decltype(CPP_true_fn(::concepts::detail::xNil{}))>
0175
0176 #define CPP_NOT(...) (!CPP_BOOL(__VA_ARGS__))
0177 #else
0178 #define CPP_BOOL(...) __VA_ARGS__
0179 #define CPP_TRUE_FN CPP_true_fn(::concepts::detail::xNil{})
0180 #define CPP_NOT(...) (!(__VA_ARGS__))
0181 #endif
0182
0183 #define CPP_assert(...) \
0184 static_assert(static_cast<bool>(__VA_ARGS__), \
0185 "Concept assertion failed : " #__VA_ARGS__)
0186
0187 #define CPP_assert_msg static_assert
0188
0189 #if CPP_CXX_CONCEPTS || defined(CPP_DOXYGEN_INVOKED)
0190 #define CPP_concept META_CONCEPT
0191 #define CPP_and &&
0192
0193 #else
0194 #define CPP_concept CPP_INLINE_VAR constexpr bool
0195 #define CPP_and CPP_and_sfinae
0196
0197 #endif
0198
0199
0200
0201
0202
0203
0204
0205
0206 #if CPP_CXX_CONCEPTS
0207 #if defined(CPP_DOXYGEN_INVOKED)
0208 #define CPP_template(...) template<__VA_ARGS__> CPP_TEMPLATE_EXPAND_
0209 #define CPP_TEMPLATE_EXPAND_(X,Y) X Y
0210 #else
0211 #define CPP_template(...) template<__VA_ARGS__ CPP_TEMPLATE_AUX_
0212 #endif
0213 #define CPP_template_def CPP_template
0214 #define CPP_member
0215 #define CPP_ctor(TYPE) TYPE CPP_CTOR_IMPL_1_
0216 #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 10
0217 #define CPP_auto_member template<typename...>
0218 #else
0219 #define CPP_auto_member
0220 #endif
0221
0222
0223 #define CPP_CTOR_IMPL_1_(...) (__VA_ARGS__) CPP_PP_EXPAND
0224
0225
0226 #define CPP_TEMPLATE_AUX_(...) \
0227 > CPP_PP_CAT( \
0228 CPP_TEMPLATE_AUX_, \
0229 CPP_TEMPLATE_AUX_WHICH_(__VA_ARGS__,))(__VA_ARGS__)
0230
0231
0232 #define CPP_TEMPLATE_AUX_WHICH_(FIRST, ...) \
0233 CPP_PP_EVAL( \
0234 CPP_PP_CHECK, \
0235 CPP_PP_CAT(CPP_TEMPLATE_PROBE_CONCEPT_, FIRST))
0236
0237
0238 #define CPP_TEMPLATE_PROBE_CONCEPT_concept \
0239 CPP_PP_PROBE(~)
0240
0241
0242
0243 #define CPP_TEMPLATE_AUX_0(...) __VA_ARGS__
0244
0245
0246
0247 #define CPP_TEMPLATE_AUX_1(DECL, ...) \
0248 CPP_concept CPP_CONCEPT_NAME_(DECL) = __VA_ARGS__
0249
0250 #if defined(CPP_DOXYGEN_INVOKED)
0251 #define CPP_concept_ref(NAME, ...) \
0252 NAME<__VA_ARGS__>
0253 #else
0254 #define CPP_concept_ref(NAME, ...) \
0255 CPP_PP_CAT(NAME, concept_)<__VA_ARGS__>
0256 #endif
0257
0258 #else
0259
0260 #define CPP_template CPP_template_sfinae
0261 #define CPP_template_def CPP_template_def_sfinae
0262 #define CPP_member CPP_member_sfinae
0263 #define CPP_auto_member CPP_member_sfinae
0264 #define CPP_ctor CPP_ctor_sfinae
0265 #define CPP_concept_ref(NAME, ...) \
0266 (1u == sizeof(CPP_PP_CAT(NAME, concept_)( \
0267 (::concepts::detail::tag<__VA_ARGS__>*)nullptr)))
0268
0269
0270 #define CPP_TEMPLATE_AUX_ CPP_TEMPLATE_SFINAE_AUX_
0271
0272 #endif
0273
0274 #define CPP_template_sfinae(...) \
0275 CPP_PP_IGNORE_CXX2A_COMPAT_BEGIN \
0276 template<__VA_ARGS__ CPP_TEMPLATE_SFINAE_AUX_
0277
0278
0279 #define CPP_TEMPLATE_SFINAE_PROBE_CONCEPT_concept \
0280 CPP_PP_PROBE(~)
0281
0282
0283 #define CPP_TEMPLATE_SFINAE_AUX_WHICH_(FIRST, ...) \
0284 CPP_PP_EVAL( \
0285 CPP_PP_CHECK, \
0286 CPP_PP_CAT(CPP_TEMPLATE_SFINAE_PROBE_CONCEPT_, FIRST))
0287
0288
0289 #define CPP_TEMPLATE_SFINAE_AUX_(...) \
0290 CPP_PP_CAT( \
0291 CPP_TEMPLATE_SFINAE_AUX_, \
0292 CPP_TEMPLATE_SFINAE_AUX_WHICH_(__VA_ARGS__,))(__VA_ARGS__)
0293
0294
0295
0296 #define CPP_TEMPLATE_SFINAE_AUX_0(...) , \
0297 bool CPP_true = true, \
0298 std::enable_if_t< \
0299 CPP_PP_CAT(CPP_TEMPLATE_SFINAE_AUX_3_, __VA_ARGS__) && \
0300 CPP_BOOL(CPP_true), \
0301 int> = 0> \
0302 CPP_PP_IGNORE_CXX2A_COMPAT_END
0303
0304
0305
0306 #define CPP_TEMPLATE_SFINAE_AUX_1(DECL, ...) , \
0307 bool CPP_true = true, \
0308 std::enable_if_t<__VA_ARGS__ && CPP_BOOL(CPP_true), int> = 0> \
0309 auto CPP_CONCEPT_NAME_(DECL)( \
0310 ::concepts::detail::tag<CPP_CONCEPT_PARAMS_(DECL)>*) \
0311 -> char(&)[1]; \
0312 auto CPP_CONCEPT_NAME_(DECL)(...) -> char(&)[2] \
0313 CPP_PP_IGNORE_CXX2A_COMPAT_END
0314
0315
0316 #define CPP_CONCEPT_NAME_(DECL) \
0317 CPP_PP_EVAL( \
0318 CPP_PP_CAT, \
0319 CPP_PP_EVAL(CPP_PP_FIRST, CPP_EAT_CONCEPT_(DECL)), concept_)
0320
0321
0322 #define CPP_CONCEPT_PARAMS_(DECL) \
0323 CPP_PP_EVAL(CPP_PP_SECOND, CPP_EAT_CONCEPT_(DECL))
0324
0325
0326 #define CPP_EAT_CONCEPT_(DECL) \
0327 CPP_PP_CAT(CPP_EAT_CONCEPT_, DECL)
0328
0329
0330 #define CPP_EAT_CONCEPT_concept
0331
0332
0333 #define CPP_and_sfinae \
0334 && CPP_BOOL(CPP_true), int> = 0, std::enable_if_t<
0335
0336
0337 #define CPP_template_def_sfinae(...) \
0338 template<__VA_ARGS__ CPP_TEMPLATE_DEF_SFINAE_AUX_
0339
0340
0341 #define CPP_TEMPLATE_DEF_SFINAE_AUX_(...) , \
0342 bool CPP_true, \
0343 std::enable_if_t< \
0344 CPP_PP_CAT(CPP_TEMPLATE_SFINAE_AUX_3_, __VA_ARGS__) && \
0345 CPP_BOOL(CPP_true), \
0346 int>>
0347
0348
0349 #define CPP_and_sfinae_def \
0350 && CPP_BOOL(CPP_true), int>, std::enable_if_t<
0351
0352
0353 #define CPP_TEMPLATE_SFINAE_AUX_3_requires
0354
0355
0356 #define CPP_member_sfinae \
0357 CPP_broken_friend_member
0358
0359
0360 #define CPP_ctor_sfinae(TYPE) \
0361 CPP_PP_IGNORE_CXX2A_COMPAT_BEGIN \
0362 TYPE CPP_CTOR_SFINAE_IMPL_1_
0363
0364
0365 #define CPP_CTOR_SFINAE_IMPL_1_(...) \
0366 (__VA_ARGS__ \
0367 CPP_PP_COMMA_IIF( \
0368 CPP_PP_NOT(CPP_PP_IS_NOT_EMPTY(__VA_ARGS__))) \
0369 CPP_CTOR_SFINAE_REQUIRES
0370
0371
0372 #define CPP_CTOR_SFINAE_PROBE_NOEXCEPT_noexcept \
0373 CPP_PP_PROBE(~)
0374
0375
0376 #define CPP_CTOR_SFINAE_MAKE_PROBE(FIRST,...) \
0377 CPP_PP_CAT(CPP_CTOR_SFINAE_PROBE_NOEXCEPT_, FIRST)
0378
0379
0380 #define CPP_CTOR_SFINAE_REQUIRES(...) \
0381 CPP_PP_CAT( \
0382 CPP_CTOR_SFINAE_REQUIRES_, \
0383 CPP_PP_EVAL( \
0384 CPP_PP_CHECK, \
0385 CPP_CTOR_SFINAE_MAKE_PROBE(__VA_ARGS__,)))(__VA_ARGS__)
0386
0387
0388
0389 #define CPP_CTOR_SFINAE_REQUIRES_0(...) \
0390 std::enable_if_t< \
0391 CPP_PP_CAT(CPP_TEMPLATE_SFINAE_AUX_3_, __VA_ARGS__) && CPP_TRUE_FN, \
0392 ::concepts::detail::Nil \
0393 > = {}) \
0394 CPP_PP_IGNORE_CXX2A_COMPAT_END
0395
0396
0397
0398 #define CPP_CTOR_SFINAE_REQUIRES_1(...) \
0399 std::enable_if_t< \
0400 CPP_PP_EVAL(CPP_PP_CAT, \
0401 CPP_TEMPLATE_SFINAE_AUX_3_, \
0402 CPP_PP_CAT(CPP_CTOR_SFINAE_EAT_NOEXCEPT_, __VA_ARGS__)) && CPP_TRUE_FN,\
0403 ::concepts::detail::Nil \
0404 > = {}) \
0405 CPP_PP_EXPAND(CPP_PP_CAT(CPP_CTOR_SFINAE_SHOW_NOEXCEPT_, __VA_ARGS__)))
0406
0407
0408 #define CPP_CTOR_SFINAE_EAT_NOEXCEPT_noexcept(...)
0409
0410
0411 #define CPP_CTOR_SFINAE_SHOW_NOEXCEPT_noexcept(...) \
0412 noexcept(__VA_ARGS__) \
0413 CPP_PP_IGNORE_CXX2A_COMPAT_END \
0414 CPP_PP_EAT CPP_PP_LPAREN
0415
0416 #ifdef CPP_DOXYGEN_INVOKED
0417
0418 #define CPP_broken_friend_ret(...) \
0419 __VA_ARGS__ CPP_PP_EXPAND
0420
0421 #else
0422 #define CPP_broken_friend_ret(...) \
0423 ::concepts::return_t< \
0424 __VA_ARGS__, \
0425 std::enable_if_t<CPP_BROKEN_FRIEND_RETURN_TYPE_AUX_
0426
0427
0428 #define CPP_BROKEN_FRIEND_RETURN_TYPE_AUX_(...) \
0429 CPP_BROKEN_FRIEND_RETURN_TYPE_AUX_3_(CPP_PP_CAT( \
0430 CPP_TEMPLATE_AUX_2_, __VA_ARGS__))
0431
0432
0433 #define CPP_TEMPLATE_AUX_2_requires
0434
0435
0436 #define CPP_BROKEN_FRIEND_RETURN_TYPE_AUX_3_(...) \
0437 (__VA_ARGS__ && CPP_TRUE_FN)>>
0438
0439 #ifdef CPP_WORKAROUND_MSVC_779763
0440
0441 #define CPP_broken_friend_member \
0442 template<::concepts::detail::CPP_true_t const &CPP_true_fn = \
0443 ::concepts::detail::CPP_true_fn_>
0444
0445 #else
0446
0447 #define CPP_broken_friend_member \
0448 template<bool (&CPP_true_fn)(::concepts::detail::xNil) = \
0449 ::concepts::detail::CPP_true_fn>
0450
0451 #endif
0452 #endif
0453
0454 #if CPP_CXX_CONCEPTS
0455 #if defined(CPP_DOXYGEN_INVOKED)
0456 #define CPP_requires(NAME, REQS) \
0457 concept NAME = \
0458 CPP_PP_CAT(CPP_REQUIRES_, REQS)
0459 #define CPP_requires_ref(NAME, ...) \
0460 NAME<__VA_ARGS__>
0461 #else
0462 #define CPP_requires(NAME, REQS) \
0463 CPP_concept CPP_PP_CAT(NAME, requires_) = \
0464 CPP_PP_CAT(CPP_REQUIRES_, REQS)
0465 #define CPP_requires_ref(NAME, ...) \
0466 CPP_PP_CAT(NAME, requires_)<__VA_ARGS__>
0467 #endif
0468
0469
0470 #define CPP_REQUIRES_requires(...) \
0471 requires(__VA_ARGS__) CPP_REQUIRES_AUX_
0472
0473
0474 #define CPP_REQUIRES_AUX_(...) \
0475 { __VA_ARGS__; }
0476
0477 #else
0478 #define CPP_requires(NAME, REQS) \
0479 auto CPP_PP_CAT(NAME, requires_test_) \
0480 CPP_REQUIRES_AUX_(NAME, CPP_REQUIRES_ ## REQS)
0481
0482 #define CPP_requires_ref(NAME, ...) \
0483 (1u == sizeof(CPP_PP_CAT(NAME, requires_)( \
0484 (::concepts::detail::tag<__VA_ARGS__>*)nullptr)))
0485
0486
0487 #define CPP_REQUIRES_requires(...) \
0488 (__VA_ARGS__) -> decltype CPP_REQUIRES_RETURN_
0489
0490
0491 #define CPP_REQUIRES_RETURN_(...) (__VA_ARGS__, void()) {}
0492
0493
0494 #define CPP_REQUIRES_AUX_(NAME, ...) \
0495 __VA_ARGS__ \
0496 template<typename... As> \
0497 auto CPP_PP_CAT(NAME, requires_)( \
0498 ::concepts::detail::tag<As...> *, \
0499 decltype(&CPP_PP_CAT(NAME, requires_test_)<As...>) = nullptr) \
0500 -> char(&)[1]; \
0501 auto CPP_PP_CAT(NAME, requires_)(...) -> char(&)[2]
0502
0503 #endif
0504
0505 #if CPP_CXX_CONCEPTS
0506 #define CPP_ret(...) \
0507 __VA_ARGS__ CPP_PP_EXPAND
0508 #else
0509 #define CPP_ret \
0510 CPP_broken_friend_ret
0511 #endif
0512
0513
0514
0515 #if CPP_CXX_CONCEPTS
0516
0517
0518 #define CPP_FUN_IMPL_1_(...) \
0519 (__VA_ARGS__) \
0520 CPP_PP_EXPAND
0521
0522 #define CPP_fun(X) X CPP_FUN_IMPL_1_
0523 #else
0524
0525 #define CPP_FUN_IMPL_1_(...) \
0526 (__VA_ARGS__ \
0527 CPP_PP_COMMA_IIF( \
0528 CPP_PP_NOT(CPP_PP_IS_NOT_EMPTY(__VA_ARGS__))) \
0529 CPP_FUN_IMPL_REQUIRES
0530
0531
0532 #define CPP_FUN_IMPL_REQUIRES(...) \
0533 CPP_PP_EVAL2_( \
0534 CPP_FUN_IMPL_SELECT_CONST_, \
0535 (__VA_ARGS__,) \
0536 )(__VA_ARGS__)
0537
0538
0539 #define CPP_FUN_IMPL_SELECT_CONST_(MAYBE_CONST, ...) \
0540 CPP_PP_CAT(CPP_FUN_IMPL_SELECT_CONST_, \
0541 CPP_PP_EVAL(CPP_PP_CHECK, CPP_PP_CAT( \
0542 CPP_PP_PROBE_CONST_PROBE_, MAYBE_CONST)))
0543
0544
0545 #define CPP_PP_PROBE_CONST_PROBE_const CPP_PP_PROBE(~)
0546
0547
0548 #define CPP_FUN_IMPL_SELECT_CONST_1(...) \
0549 CPP_PP_EVAL( \
0550 CPP_FUN_IMPL_SELECT_CONST_NOEXCEPT_, \
0551 CPP_PP_CAT(CPP_FUN_IMPL_EAT_CONST_, __VA_ARGS__),)( \
0552 CPP_PP_CAT(CPP_FUN_IMPL_EAT_CONST_, __VA_ARGS__))
0553
0554
0555 #define CPP_FUN_IMPL_SELECT_CONST_NOEXCEPT_(MAYBE_NOEXCEPT, ...) \
0556 CPP_PP_CAT(CPP_FUN_IMPL_SELECT_CONST_NOEXCEPT_, \
0557 CPP_PP_EVAL2(CPP_PP_CHECK, CPP_PP_CAT( \
0558 CPP_PP_PROBE_NOEXCEPT_PROBE_, MAYBE_NOEXCEPT)))
0559
0560
0561 #define CPP_PP_PROBE_NOEXCEPT_PROBE_noexcept CPP_PP_PROBE(~)
0562
0563
0564 #define CPP_FUN_IMPL_SELECT_CONST_NOEXCEPT_0(...) \
0565 std::enable_if_t< \
0566 CPP_PP_EVAL( \
0567 CPP_PP_CAT, \
0568 CPP_FUN_IMPL_EAT_REQUIRES_, \
0569 __VA_ARGS__) && CPP_TRUE_FN, \
0570 ::concepts::detail::Nil \
0571 > = {}) const \
0572 CPP_PP_IGNORE_CXX2A_COMPAT_END
0573
0574
0575 #define CPP_FUN_IMPL_SELECT_CONST_NOEXCEPT_1(...) \
0576 std::enable_if_t< \
0577 CPP_PP_EVAL( \
0578 CPP_PP_CAT, \
0579 CPP_FUN_IMPL_EAT_REQUIRES_, \
0580 CPP_PP_CAT(CPP_FUN_IMPL_EAT_NOEXCEPT_, __VA_ARGS__)) && CPP_TRUE_FN,\
0581 ::concepts::detail::Nil \
0582 > = {}) const \
0583 CPP_PP_EXPAND(CPP_PP_CAT(CPP_FUN_IMPL_SHOW_NOEXCEPT_, __VA_ARGS__)))
0584
0585
0586 #define CPP_FUN_IMPL_EAT_NOEXCEPT_noexcept(...)
0587
0588
0589 #define CPP_FUN_IMPL_SHOW_NOEXCEPT_noexcept(...) \
0590 noexcept(__VA_ARGS__) CPP_PP_IGNORE_CXX2A_COMPAT_END \
0591 CPP_PP_EAT CPP_PP_LPAREN
0592
0593
0594 #define CPP_FUN_IMPL_SELECT_CONST_0(...) \
0595 CPP_PP_EVAL_( \
0596 CPP_FUN_IMPL_SELECT_NONCONST_NOEXCEPT_, \
0597 (__VA_ARGS__,) \
0598 )(__VA_ARGS__)
0599
0600
0601 #define CPP_FUN_IMPL_SELECT_NONCONST_NOEXCEPT_(MAYBE_NOEXCEPT, ...) \
0602 CPP_PP_CAT(CPP_FUN_IMPL_SELECT_NONCONST_NOEXCEPT_, \
0603 CPP_PP_EVAL2(CPP_PP_CHECK, CPP_PP_CAT( \
0604 CPP_PP_PROBE_NOEXCEPT_PROBE_, MAYBE_NOEXCEPT)))
0605
0606
0607 #define CPP_FUN_IMPL_SELECT_NONCONST_NOEXCEPT_0(...) \
0608 std::enable_if_t< \
0609 CPP_PP_CAT(CPP_FUN_IMPL_EAT_REQUIRES_, __VA_ARGS__) && CPP_TRUE_FN, \
0610 ::concepts::detail::Nil \
0611 > = {}) \
0612 CPP_PP_IGNORE_CXX2A_COMPAT_END
0613
0614
0615 #define CPP_FUN_IMPL_SELECT_NONCONST_NOEXCEPT_1(...) \
0616 std::enable_if_t< \
0617 CPP_PP_EVAL( \
0618 CPP_PP_CAT, \
0619 CPP_FUN_IMPL_EAT_REQUIRES_, \
0620 CPP_PP_CAT(CPP_FUN_IMPL_EAT_NOEXCEPT_, __VA_ARGS__) \
0621 ) && CPP_TRUE_FN, \
0622 ::concepts::detail::Nil \
0623 > = {}) \
0624 CPP_PP_EXPAND(CPP_PP_CAT(CPP_FUN_IMPL_SHOW_NOEXCEPT_, __VA_ARGS__)))
0625
0626
0627 #define CPP_FUN_IMPL_EAT_CONST_const
0628
0629
0630 #define CPP_FUN_IMPL_EAT_REQUIRES_requires
0631
0632
0633
0634
0635
0636
0637
0638
0639
0640
0641
0642 #define CPP_fun(X) CPP_PP_IGNORE_CXX2A_COMPAT_BEGIN X CPP_FUN_IMPL_1_
0643 #endif
0644
0645
0646
0647
0648
0649
0650
0651
0652
0653 #define CPP_auto_fun(X) X CPP_AUTO_FUN_IMPL_
0654
0655
0656 #define CPP_AUTO_FUN_IMPL_(...) (__VA_ARGS__) CPP_AUTO_FUN_RETURNS_
0657
0658
0659 #define CPP_AUTO_FUN_RETURNS_(...) \
0660 CPP_PP_EVAL2_( \
0661 CPP_AUTO_FUN_SELECT_RETURNS_, \
0662 (__VA_ARGS__,) \
0663 )(__VA_ARGS__)
0664
0665
0666 #define CPP_AUTO_FUN_SELECT_RETURNS_(MAYBE_CONST, ...) \
0667 CPP_PP_CAT(CPP_AUTO_FUN_RETURNS_CONST_, \
0668 CPP_PP_EVAL(CPP_PP_CHECK, CPP_PP_CAT( \
0669 CPP_PP_PROBE_CONST_MUTABLE_PROBE_, MAYBE_CONST)))
0670
0671
0672 #define CPP_PP_PROBE_CONST_MUTABLE_PROBE_const CPP_PP_PROBE_N(~, 1)
0673
0674
0675 #define CPP_PP_PROBE_CONST_MUTABLE_PROBE_mutable CPP_PP_PROBE_N(~, 2)
0676
0677
0678 #define CPP_PP_EAT_MUTABLE_mutable
0679
0680
0681 #define CPP_AUTO_FUN_RETURNS_CONST_2(...) \
0682 CPP_PP_CAT(CPP_PP_EAT_MUTABLE_, __VA_ARGS__) CPP_AUTO_FUN_RETURNS_CONST_0
0683
0684
0685 #define CPP_AUTO_FUN_RETURNS_CONST_1(...) \
0686 __VA_ARGS__ CPP_AUTO_FUN_RETURNS_CONST_0
0687
0688
0689 #define CPP_AUTO_FUN_RETURNS_CONST_0(...) \
0690 CPP_PP_EVAL(CPP_AUTO_FUN_DECLTYPE_NOEXCEPT_, \
0691 CPP_PP_CAT(CPP_AUTO_FUN_RETURNS_, __VA_ARGS__))
0692
0693
0694 #define CPP_AUTO_FUN_RETURNS_return
0695
0696 #ifdef __cpp_guaranteed_copy_elision
0697
0698 #define CPP_AUTO_FUN_DECLTYPE_NOEXCEPT_(...) \
0699 noexcept(noexcept(__VA_ARGS__)) -> decltype(__VA_ARGS__) \
0700 { return (__VA_ARGS__); }
0701
0702 #else
0703
0704 #define CPP_AUTO_FUN_DECLTYPE_NOEXCEPT_(...) \
0705 noexcept(noexcept(decltype(__VA_ARGS__)(__VA_ARGS__))) -> \
0706 decltype(__VA_ARGS__) \
0707 { return (__VA_ARGS__); }
0708
0709 #endif
0710
0711 #if defined(CPP_DOXYGEN_INVOKED)
0712 #define concept(NAME) concept NAME CPP_CONCEPT_EQUALS_
0713 #define CPP_CONCEPT_EQUALS_(...) =
0714 #endif
0715
0716 namespace concepts
0717 {
0718 template<bool B>
0719 using bool_ = std::integral_constant<bool, B>;
0720
0721 #if defined(__cpp_fold_expressions) && __cpp_fold_expressions >= 201603
0722 template<bool...Bs>
0723 CPP_INLINE_VAR constexpr bool and_v = (Bs &&...);
0724
0725 template<bool...Bs>
0726 CPP_INLINE_VAR constexpr bool or_v = (Bs ||...);
0727 #else
0728 namespace detail
0729 {
0730 template<bool...>
0731 struct bools;
0732 }
0733
0734 template<bool...Bs>
0735 CPP_INLINE_VAR constexpr bool and_v =
0736 META_IS_SAME(detail::bools<Bs..., true>, detail::bools<true, Bs...>);
0737
0738 template<bool...Bs>
0739 CPP_INLINE_VAR constexpr bool or_v =
0740 !META_IS_SAME(detail::bools<Bs..., false>, detail::bools<false, Bs...>);
0741 #endif
0742
0743 template<typename>
0744 struct return_t_
0745 {
0746 template<typename T>
0747 using invoke = T;
0748 };
0749
0750 template<typename T, typename EnableIf>
0751 using return_t = meta::invoke<return_t_<EnableIf>, T>;
0752
0753
0754 namespace detail
0755 {
0756 struct ignore
0757 {
0758 template<class... Args>
0759 constexpr ignore(Args&&...) noexcept {}
0760 };
0761
0762 template<class>
0763 constexpr bool true_()
0764 {
0765 return true;
0766 }
0767
0768 template<typename...>
0769 struct tag;
0770
0771 template<typename T>
0772 CPP_INLINE_VAR constexpr T instance_ = T{};
0773
0774 template<typename>
0775 constexpr bool requires_()
0776 {
0777 return true;
0778 }
0779
0780 struct Nil
0781 {};
0782
0783 #ifdef CPP_WORKAROUND_MSVC_779763
0784 enum class xNil {};
0785
0786 struct CPP_true_t
0787 {
0788 constexpr bool operator()(Nil) const noexcept
0789 {
0790 return true;
0791 }
0792 constexpr bool operator()(xNil) const noexcept
0793 {
0794 return true;
0795 }
0796 };
0797
0798 CPP_INLINE_VAR constexpr CPP_true_t CPP_true_fn_ {};
0799
0800 constexpr bool CPP_true_fn(xNil)
0801 {
0802 return true;
0803 }
0804 #else
0805 using xNil = Nil;
0806 #endif
0807
0808 constexpr bool CPP_true_fn(Nil)
0809 {
0810 return true;
0811 }
0812 }
0813
0814
0815 #if defined(__clang__) || defined(_MSC_VER)
0816 template<bool B>
0817 std::enable_if_t<B> requires_()
0818 {}
0819 #else
0820 template<bool B>
0821 CPP_INLINE_VAR constexpr std::enable_if_t<B, int> requires_ = 0;
0822 #endif
0823
0824 inline namespace defs
0825 {
0826
0827
0828
0829
0830
0831
0832 template<bool B>
0833 CPP_concept is_true = B;
0834
0835
0836
0837 template<typename... Args>
0838 CPP_concept type = true;
0839
0840
0841
0842 template<class T, template<typename...> class Trait, typename... Args>
0843 CPP_concept satisfies =
0844 static_cast<bool>(Trait<T, Args...>::type::value);
0845
0846
0847
0848
0849
0850
0851
0852 template<typename A, typename B>
0853 CPP_concept same_as =
0854 META_IS_SAME(A, B) && META_IS_SAME(B, A);
0855
0856
0857
0858
0859 template<typename A, typename B>
0860 CPP_concept not_same_as_ =
0861 (!same_as<remove_cvref_t<A>, remove_cvref_t<B>>);
0862
0863
0864
0865
0866
0867
0868
0869
0870 template<typename From, typename To>
0871 CPP_concept implicitly_convertible_to =
0872 std::is_convertible<std::add_rvalue_reference_t<From>, To>::value;
0873
0874
0875
0876 template<typename From, typename To>
0877 CPP_requires(explicitly_convertible_to_,
0878 requires(From(*from)())
0879 (
0880 static_cast<To>(from())
0881 ));
0882
0883
0884 template<typename From, typename To>
0885 CPP_concept explicitly_convertible_to =
0886 CPP_requires_ref(concepts::explicitly_convertible_to_, From, To);
0887
0888
0889
0890 template<typename From, typename To>
0891 CPP_concept convertible_to =
0892 implicitly_convertible_to<From, To> &&
0893 explicitly_convertible_to<From, To>;
0894
0895
0896
0897 CPP_template(typename T, typename U)(
0898 concept (derived_from_)(T, U),
0899 convertible_to<T const volatile *, U const volatile *>
0900 );
0901
0902
0903 template<typename T, typename U>
0904 CPP_concept derived_from =
0905 META_IS_BASE_OF(U, T) &&
0906 CPP_concept_ref(concepts::derived_from_, T, U);
0907
0908
0909
0910 CPP_template(typename T, typename U)(
0911 concept (common_reference_with_)(T, U),
0912 same_as<common_reference_t<T, U>, common_reference_t<U, T>> CPP_and
0913 convertible_to<T, common_reference_t<T, U>> CPP_and
0914 convertible_to<U, common_reference_t<T, U>>
0915 );
0916
0917
0918 template<typename T, typename U>
0919 CPP_concept common_reference_with =
0920 CPP_concept_ref(concepts::common_reference_with_, T, U);
0921
0922
0923
0924 CPP_template(typename T, typename U)(
0925 concept (common_with_)(T, U),
0926 same_as<common_type_t<T, U>, common_type_t<U, T>> CPP_and
0927 convertible_to<T, common_type_t<T, U>> CPP_and
0928 convertible_to<U, common_type_t<T, U>> CPP_and
0929 common_reference_with<
0930 std::add_lvalue_reference_t<T const>,
0931 std::add_lvalue_reference_t<U const>> CPP_and
0932 common_reference_with<
0933 std::add_lvalue_reference_t<common_type_t<T, U>>,
0934 common_reference_t<
0935 std::add_lvalue_reference_t<T const>,
0936 std::add_lvalue_reference_t<U const>>>
0937 );
0938
0939
0940 template<typename T, typename U>
0941 CPP_concept common_with =
0942 CPP_concept_ref(concepts::common_with_, T, U);
0943
0944
0945
0946 template<typename T>
0947 CPP_concept integral =
0948 std::is_integral<T>::value;
0949
0950
0951
0952 template<typename T>
0953 CPP_concept signed_integral =
0954 integral<T> &&
0955 std::is_signed<T>::value;
0956
0957
0958
0959 template<typename T>
0960 CPP_concept unsigned_integral =
0961 integral<T> &&
0962 !signed_integral<T>;
0963
0964
0965
0966 template<typename T, typename U>
0967 CPP_requires(assignable_from_,
0968 requires(T t, U && u)
0969 (
0970 t = (U &&) u,
0971 requires_<same_as<T, decltype(t = (U &&) u)>>
0972 ));
0973
0974
0975 template<typename T, typename U>
0976 CPP_concept assignable_from =
0977 std::is_lvalue_reference<T>::value &&
0978 common_reference_with<detail::as_cref_t<T>, detail::as_cref_t<U>> &&
0979 CPP_requires_ref(defs::assignable_from_, T, U);
0980
0981
0982
0983 template<typename T>
0984 CPP_requires(swappable_,
0985 requires(T & t, T & u)
0986 (
0987 concepts::swap(t, u)
0988 ));
0989
0990
0991 template<typename T>
0992 CPP_concept swappable =
0993 CPP_requires_ref(defs::swappable_, T);
0994
0995
0996
0997 template<typename T, typename U>
0998 CPP_requires(swappable_with_,
0999 requires(T && t, U && u)
1000 (
1001 concepts::swap((T &&) t, (T &&) t),
1002 concepts::swap((U &&) u, (U &&) u),
1003 concepts::swap((U &&) u, (T &&) t),
1004 concepts::swap((T &&) t, (U &&) u)
1005 ));
1006
1007
1008 template<typename T, typename U>
1009 CPP_concept swappable_with =
1010 common_reference_with<detail::as_cref_t<T>, detail::as_cref_t<U>> &&
1011 CPP_requires_ref(defs::swappable_with_, T, U);
1012
1013 }
1014
1015 namespace detail
1016 {
1017
1018
1019 template<typename T>
1020 CPP_concept boolean_testable_impl_ = convertible_to<T, bool>;
1021
1022
1023
1024 template<typename T>
1025 CPP_requires(boolean_testable_frag_,
1026 requires(T && t)
1027 (
1028 !(T&&) t,
1029 concepts::requires_<boolean_testable_impl_<decltype(!(T&&) t)>>
1030 ));
1031
1032
1033
1034 template<typename T>
1035 CPP_concept boolean_testable_ =
1036 CPP_requires_ref(boolean_testable_frag_, T) &&
1037 boolean_testable_impl_<T>;
1038
1039 CPP_DIAGNOSTIC_PUSH
1040 CPP_DIAGNOSTIC_IGNORE_FLOAT_EQUAL
1041
1042
1043
1044 template<typename T, typename U>
1045 CPP_requires(weakly_equality_comparable_with_frag_,
1046 requires(detail::as_cref_t<T> t, detail::as_cref_t<U> u)
1047 (
1048 concepts::requires_<boolean_testable_<decltype(t == u)>>,
1049 concepts::requires_<boolean_testable_<decltype(t != u)>>,
1050 concepts::requires_<boolean_testable_<decltype(u == t)>>,
1051 concepts::requires_<boolean_testable_<decltype(u != t)>>
1052 ));
1053
1054
1055 template<typename T, typename U>
1056 CPP_concept weakly_equality_comparable_with_ =
1057 CPP_requires_ref(weakly_equality_comparable_with_frag_, T, U);
1058
1059
1060
1061 template<typename T, typename U>
1062 CPP_requires(partially_ordered_with_frag_,
1063 requires(detail::as_cref_t<T>& t, detail::as_cref_t<U>& u)
1064 (
1065 concepts::requires_<boolean_testable_<decltype(t < u)>>,
1066 concepts::requires_<boolean_testable_<decltype(t > u)>>,
1067 concepts::requires_<boolean_testable_<decltype(t <= u)>>,
1068 concepts::requires_<boolean_testable_<decltype(t >= u)>>,
1069 concepts::requires_<boolean_testable_<decltype(u < t)>>,
1070 concepts::requires_<boolean_testable_<decltype(u > t)>>,
1071 concepts::requires_<boolean_testable_<decltype(u <= t)>>,
1072 concepts::requires_<boolean_testable_<decltype(u >= t)>>
1073 ));
1074
1075
1076 template<typename T, typename U>
1077 CPP_concept partially_ordered_with_ =
1078 CPP_requires_ref(partially_ordered_with_frag_, T, U);
1079
1080 CPP_DIAGNOSTIC_POP
1081 }
1082
1083 inline namespace defs
1084 {
1085
1086
1087
1088
1089
1090
1091 template<typename T>
1092 CPP_concept equality_comparable =
1093 detail::weakly_equality_comparable_with_<T, T>;
1094
1095
1096
1097 CPP_template(typename T, typename U)(
1098 concept (equality_comparable_with_)(T, U),
1099 equality_comparable<
1100 common_reference_t<detail::as_cref_t<T>, detail::as_cref_t<U>>>
1101 );
1102
1103
1104 template<typename T, typename U>
1105 CPP_concept equality_comparable_with =
1106 equality_comparable<T> &&
1107 equality_comparable<U> &&
1108 detail::weakly_equality_comparable_with_<T, U> &&
1109 common_reference_with<detail::as_cref_t<T>, detail::as_cref_t<U>> &&
1110 CPP_concept_ref(concepts::equality_comparable_with_, T, U);
1111
1112
1113
1114 template<typename T>
1115 CPP_concept totally_ordered =
1116 equality_comparable<T> &&
1117 detail::partially_ordered_with_<T, T>;
1118
1119
1120
1121 CPP_template(typename T, typename U)(
1122 concept (totally_ordered_with_)(T, U),
1123 totally_ordered<
1124 common_reference_t<
1125 detail::as_cref_t<T>,
1126 detail::as_cref_t<U>>> CPP_and
1127 detail::partially_ordered_with_<T, U>);
1128
1129
1130
1131 template<typename T, typename U>
1132 CPP_concept totally_ordered_with =
1133 totally_ordered<T> &&
1134 totally_ordered<U> &&
1135 equality_comparable_with<T, U> &&
1136 CPP_concept_ref(concepts::totally_ordered_with_, T, U);
1137
1138
1139
1140
1141
1142
1143
1144 template<typename T>
1145 CPP_concept destructible =
1146 std::is_nothrow_destructible<T>::value;
1147
1148
1149
1150 template<typename T, typename... Args>
1151 CPP_concept constructible_from =
1152 destructible<T> &&
1153 META_IS_CONSTRUCTIBLE(T, Args...);
1154
1155
1156
1157 template<typename T>
1158 CPP_concept default_constructible =
1159 constructible_from<T>;
1160
1161
1162
1163 template<typename T>
1164 CPP_concept move_constructible =
1165 constructible_from<T, T> &&
1166 convertible_to<T, T>;
1167
1168
1169
1170 CPP_template(typename T)(
1171 concept (copy_constructible_)(T),
1172 constructible_from<T, T &> &&
1173 constructible_from<T, T const &> &&
1174 constructible_from<T, T const> &&
1175 convertible_to<T &, T> &&
1176 convertible_to<T const &, T> &&
1177 convertible_to<T const, T>);
1178
1179
1180 template<typename T>
1181 CPP_concept copy_constructible =
1182 move_constructible<T> &&
1183 CPP_concept_ref(concepts::copy_constructible_, T);
1184
1185
1186
1187 CPP_template(typename T)(
1188 concept (move_assignable_)(T),
1189 assignable_from<T &, T>
1190 );
1191
1192
1193 template<typename T>
1194 CPP_concept movable =
1195 std::is_object<T>::value &&
1196 move_constructible<T> &&
1197 CPP_concept_ref(concepts::move_assignable_, T) &&
1198 swappable<T>;
1199
1200
1201
1202 CPP_template(typename T)(
1203 concept (copy_assignable_)(T),
1204 assignable_from<T &, T const &>
1205 );
1206
1207
1208 template<typename T>
1209 CPP_concept copyable =
1210 copy_constructible<T> &&
1211 movable<T> &&
1212 CPP_concept_ref(concepts::copy_assignable_, T);
1213
1214
1215
1216 template<typename T>
1217 CPP_concept semiregular =
1218 copyable<T> &&
1219 default_constructible<T>;
1220
1221
1222
1223
1224
1225 template<typename T>
1226 CPP_concept regular =
1227 semiregular<T> &&
1228 equality_comparable<T>;
1229
1230 }
1231 }
1232
1233 #endif