1 /// \file
2 //  CPP, the Concepts PreProcessor library
3 //
4 //  Copyright Eric Niebler 2018-present
5 //  Copyright (c) 2018-present, Facebook, Inc.
6 //  Copyright (c) 2020-present, Google LLC.
7 //
8 //  Use, modification and distribution is subject to the
9 //  Boost Software License, Version 1.0. (See accompanying
10 //  file LICENSE_1_0.txt or copy at
11 //  http://www.boost.org/LICENSE_1_0.txt)
12 //
13 // This source code is licensed under the MIT license found in the
14 // LICENSE file in the root directory of this source tree.
15 //
16 // Project home: https://github.com/ericniebler/range-v3
17 //
18 
19 #ifndef CPP_CONCEPTS_HPP
20 #define CPP_CONCEPTS_HPP
21 
22 // clang-format off
23 
24 #include <initializer_list>
25 #include <utility>
26 #include <type_traits>
27 #include <concepts/swap.hpp>
28 #include <concepts/type_traits.hpp>
29 
30 // Disable buggy clang compatibility warning about "requires" and "concept" being
31 // C++20 keywords.
32 // https://bugs.llvm.org/show_bug.cgi?id=43708
33 #if defined(__clang__) && __cplusplus <= 201703L
34 #define CPP_PP_IGNORE_CXX2A_COMPAT_BEGIN                                                \
35     CPP_DIAGNOSTIC_PUSH                                                                 \
36     CPP_DIAGNOSTIC_IGNORE_CPP2A_COMPAT
37 
38 #define CPP_PP_IGNORE_CXX2A_COMPAT_END                                                  \
39     CPP_DIAGNOSTIC_POP
40 
41 #else
42 #define CPP_PP_IGNORE_CXX2A_COMPAT_BEGIN
43 #define CPP_PP_IGNORE_CXX2A_COMPAT_END
44 #endif
45 
46 #if defined(_MSC_VER) && !defined(__clang__)
47 #define CPP_WORKAROUND_MSVC_779763 // FATAL_UNREACHABLE calling constexpr function via template parameter
48 #define CPP_WORKAROUND_MSVC_784772 // Failure to invoke *explicit* bool conversion in a constant expression
49 #endif
50 
51 #if !defined(CPP_CXX_CONCEPTS)
52 #ifdef CPP_DOXYGEN_INVOKED
53 #define CPP_CXX_CONCEPTS 201800L
54 #elif defined(__cpp_concepts) && __cpp_concepts > 0
55 // gcc-6 concepts are too buggy to use
56 #if !defined(__GNUC__) || defined(__clang__) || __GNUC__ >= 7
57 #define CPP_CXX_CONCEPTS __cpp_concepts
58 #else
59 #define CPP_CXX_CONCEPTS 0L
60 #endif
61 #else
62 #define CPP_CXX_CONCEPTS 0L
63 #endif
64 #endif
65 
66 #define CPP_PP_CAT_(X, ...)  X ## __VA_ARGS__
67 #define CPP_PP_CAT(X, ...)   CPP_PP_CAT_(X, __VA_ARGS__)
68 
69 #define CPP_PP_EVAL_(X, ARGS) X ARGS
70 #define CPP_PP_EVAL(X, ...) CPP_PP_EVAL_(X, (__VA_ARGS__))
71 
72 #define CPP_PP_EVAL2_(X, ARGS) X ARGS
73 #define CPP_PP_EVAL2(X, ...) CPP_PP_EVAL2_(X, (__VA_ARGS__))
74 
75 #define CPP_PP_EXPAND(...) __VA_ARGS__
76 #define CPP_PP_EAT(...)
77 
78 #define CPP_PP_FIRST(LIST) CPP_PP_FIRST_ LIST
79 #define CPP_PP_FIRST_(...) __VA_ARGS__ CPP_PP_EAT
80 
81 #define CPP_PP_SECOND(LIST) CPP_PP_SECOND_ LIST
82 #define CPP_PP_SECOND_(...) CPP_PP_EXPAND
83 
84 #define CPP_PP_CHECK(...) CPP_PP_EXPAND(CPP_PP_CHECK_N(__VA_ARGS__, 0,))
85 #define CPP_PP_CHECK_N(x, n, ...) n
86 #define CPP_PP_PROBE(x) x, 1,
87 #define CPP_PP_PROBE_N(x, n) x, n,
88 
89 #define CPP_PP_IS_PAREN(x) CPP_PP_CHECK(CPP_PP_IS_PAREN_PROBE x)
90 #define CPP_PP_IS_PAREN_PROBE(...) CPP_PP_PROBE(~)
91 
92 // CPP_CXX_VA_OPT
93 #ifndef CPP_CXX_VA_OPT
94 #if __cplusplus > 201703L
95 #define CPP_CXX_VA_OPT_(...) CPP_PP_CHECK(__VA_OPT__(,) 1)
96 #define CPP_CXX_VA_OPT CPP_CXX_VA_OPT_(~)
97 #else
98 #define CPP_CXX_VA_OPT 0
99 #endif
100 #endif // CPP_CXX_VA_OPT
101 
102 // The final CPP_PP_EXPAND here is to avoid
103 // https://stackoverflow.com/questions/5134523/msvc-doesnt-expand-va-args-correctly
104 #define CPP_PP_COUNT(...)                                                       \
105     CPP_PP_EXPAND(CPP_PP_COUNT_(__VA_ARGS__,                                    \
106         50, 49, 48, 47, 46, 45, 44, 43, 42, 41,                                 \
107         40, 39, 38, 37, 36, 35, 34, 33, 32, 31,                                 \
108         30, 29, 28, 27, 26, 25, 24, 23, 22, 21,                                 \
109         20, 19, 18, 17, 16, 15, 14, 13, 12, 11,                                 \
110         10, 9, 8, 7, 6, 5, 4, 3, 2, 1,))
111 
112 #define CPP_PP_COUNT_(                                                          \
113     _01, _02, _03, _04, _05, _06, _07, _08, _09, _10,                           \
114     _11, _12, _13, _14, _15, _16, _17, _18, _19, _20,                           \
115     _21, _22, _23, _24, _25, _26, _27, _28, _29, _30,                           \
116     _31, _32, _33, _34, _35, _36, _37, _38, _39, _40,                           \
117     _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, N, ...)                   \
118     N
119 
120 #define CPP_PP_IIF(BIT) CPP_PP_CAT_(CPP_PP_IIF_, BIT)
121 #define CPP_PP_IIF_0(TRUE, ...) __VA_ARGS__
122 #define CPP_PP_IIF_1(TRUE, ...) TRUE
123 
124 #define CPP_PP_LPAREN (
125 #define CPP_PP_RPAREN )
126 
127 #define CPP_PP_NOT(BIT) CPP_PP_CAT_(CPP_PP_NOT_, BIT)
128 #define CPP_PP_NOT_0 1
129 #define CPP_PP_NOT_1 0
130 
131 #define CPP_PP_EMPTY()
132 #define CPP_PP_COMMA() ,
133 #define CPP_PP_LBRACE() {
134 #define CPP_PP_RBRACE() }
135 #define CPP_PP_COMMA_IIF(X)                                                     \
136     CPP_PP_IIF(X)(CPP_PP_EMPTY, CPP_PP_COMMA)()
137 
138 #define CPP_PP_FOR_EACH(M, ...)                                                 \
139     CPP_PP_FOR_EACH_N(CPP_PP_COUNT(__VA_ARGS__), M, __VA_ARGS__)
140 #define CPP_PP_FOR_EACH_N(N, M, ...)                                            \
141     CPP_PP_CAT(CPP_PP_FOR_EACH_, N)(M, __VA_ARGS__)
142 #define CPP_PP_FOR_EACH_1(M, _1)                                                \
143     M(_1)
144 #define CPP_PP_FOR_EACH_2(M, _1, _2)                                            \
145     M(_1), M(_2)
146 #define CPP_PP_FOR_EACH_3(M, _1, _2, _3)                                        \
147     M(_1), M(_2), M(_3)
148 #define CPP_PP_FOR_EACH_4(M, _1, _2, _3, _4)                                    \
149     M(_1), M(_2), M(_3), M(_4)
150 #define CPP_PP_FOR_EACH_5(M, _1, _2, _3, _4, _5)                                \
151     M(_1), M(_2), M(_3), M(_4), M(_5)
152 #define CPP_PP_FOR_EACH_6(M, _1, _2, _3, _4, _5, _6)                            \
153     M(_1), M(_2), M(_3), M(_4), M(_5), M(_6)
154 #define CPP_PP_FOR_EACH_7(M, _1, _2, _3, _4, _5, _6, _7)                        \
155     M(_1), M(_2), M(_3), M(_4), M(_5), M(_6), M(_7)
156 #define CPP_PP_FOR_EACH_8(M, _1, _2, _3, _4, _5, _6, _7, _8)                    \
157     M(_1), M(_2), M(_3), M(_4), M(_5), M(_6), M(_7), M(_8)
158 
159 #define CPP_PP_PROBE_EMPTY_PROBE_CPP_PP_PROBE_EMPTY                             \
160     CPP_PP_PROBE(~)
161 
162 #define CPP_PP_PROBE_EMPTY()
163 #define CPP_PP_IS_NOT_EMPTY(...)                                                \
164     CPP_PP_EVAL(                                                                \
165         CPP_PP_CHECK,                                                           \
166         CPP_PP_CAT(                                                             \
167             CPP_PP_PROBE_EMPTY_PROBE_,                                          \
168             CPP_PP_PROBE_EMPTY __VA_ARGS__ ()))
169 
170 #if defined(_MSC_VER) && !defined(__clang__) && (__cplusplus <= 201703L)
171 #define CPP_BOOL(...) ::meta::bool_<__VA_ARGS__>::value
172 #define CPP_TRUE_FN                                                             \
173     !::concepts::detail::instance_<                                             \
174         decltype(CPP_true_fn(::concepts::detail::xNil{}))>
175 
176 #define CPP_NOT(...) (!CPP_BOOL(__VA_ARGS__))
177 #else
178 #define CPP_BOOL(...) __VA_ARGS__
179 #define CPP_TRUE_FN CPP_true_fn(::concepts::detail::xNil{})
180 #define CPP_NOT(...) (!(__VA_ARGS__))
181 #endif
182 
183 #define CPP_assert(...)                                                         \
184     static_assert(static_cast<bool>(__VA_ARGS__),                               \
185         "Concept assertion failed : " #__VA_ARGS__)
186 
187 #define CPP_assert_msg static_assert
188 
189 #if CPP_CXX_CONCEPTS || defined(CPP_DOXYGEN_INVOKED)
190 #define CPP_concept META_CONCEPT
191 #define CPP_and &&
192 
193 #else
194 #define CPP_concept CPP_INLINE_VAR constexpr bool
195 #define CPP_and CPP_and_sfinae
196 
197 #endif
198 
199 ////////////////////////////////////////////////////////////////////////////////
200 // CPP_template
201 // Usage:
202 //   CPP_template(typename A, typename B)
203 //     (requires Concept1<A> CPP_and Concept2<B>)
204 //   void foo(A a, B b)
205 //   {}
206 #if CPP_CXX_CONCEPTS
207 #define CPP_template(...) template<__VA_ARGS__ CPP_TEMPLATE_AUX_
208 #define CPP_template_def CPP_template
209 #define CPP_member
210 #define CPP_ctor(TYPE) TYPE CPP_CTOR_IMPL_1_
211 #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 10
212 #define CPP_auto_member template<typename...>
213 #else
214 #define CPP_auto_member
215 #endif
216 
217 #if defined(CPP_DOXYGEN_INVOKED) && CPP_DOXYGEN_INVOKED
218 /// INTERNAL ONLY
219 #define CPP_CTOR_IMPL_1_(...) (__VA_ARGS__) CPP_CTOR_IMPL_2_
220 #define CPP_CTOR_IMPL_2_(...) __VA_ARGS__ `
221 #else
222 /// INTERNAL ONLY
223 #define CPP_CTOR_IMPL_1_(...) (__VA_ARGS__) CPP_PP_EXPAND
224 #endif
225 
226 /// INTERNAL ONLY
227 #define CPP_TEMPLATE_AUX_(...)                                                  \
228     > CPP_PP_CAT(                                                               \
229         CPP_TEMPLATE_AUX_,                                                      \
230         CPP_TEMPLATE_AUX_WHICH_(__VA_ARGS__,))(__VA_ARGS__)
231 
232 /// INTERNAL ONLY
233 #define CPP_TEMPLATE_AUX_WHICH_(FIRST, ...)                                     \
234     CPP_PP_EVAL(                                                                \
235         CPP_PP_CHECK,                                                           \
236         CPP_PP_CAT(CPP_TEMPLATE_PROBE_CONCEPT_, FIRST))
237 
238 /// INTERNAL ONLY
239 #define CPP_TEMPLATE_PROBE_CONCEPT_concept                                      \
240     CPP_PP_PROBE(~)
241 
242 #if defined(CPP_DOXYGEN_INVOKED) && CPP_DOXYGEN_INVOKED
243 // A template with a requires clause. Turn the requires clause into
244 // a Doxygen precondition block.
245 /// INTERNAL ONLY
246 #define CPP_TEMPLATE_AUX_0(...) __VA_ARGS__`
247 #define requires requires `
248 
249 #else
250 // A template with a requires clause
251 /// INTERNAL ONLY
252 #define CPP_TEMPLATE_AUX_0(...) __VA_ARGS__
253 #endif
254 
255 // A concept definition
256 /// INTERNAL ONLY
257 #define CPP_TEMPLATE_AUX_1(DECL, ...)                                           \
258     CPP_concept CPP_CONCEPT_NAME_(DECL) = __VA_ARGS__
259 
260 #define CPP_concept_ref(NAME, ...)                                              \
261     CPP_PP_CAT(NAME, _concept_)<__VA_ARGS__>
262 
263 #else // ^^^^ with concepts / without concepts vvvv
264 
265 #define CPP_template CPP_template_sfinae
266 #define CPP_template_def CPP_template_def_sfinae
267 #define CPP_member CPP_member_sfinae
268 #define CPP_auto_member CPP_member_sfinae
269 #define CPP_ctor CPP_ctor_sfinae
270 #define CPP_concept_ref(NAME, ...)                                              \
271     (1u == sizeof(CPP_PP_CAT(NAME, _concept_)(                                  \
272         (::concepts::detail::tag<__VA_ARGS__>*)nullptr)))
273 
274 /// INTERNAL ONLY
275 #define CPP_TEMPLATE_AUX_ CPP_TEMPLATE_SFINAE_AUX_
276 
277 #endif
278 
279 #define CPP_template_sfinae(...)                                                \
280     CPP_PP_IGNORE_CXX2A_COMPAT_BEGIN                                            \
281     template<__VA_ARGS__ CPP_TEMPLATE_SFINAE_AUX_
282 
283 /// INTERNAL ONLY
284 #define CPP_TEMPLATE_SFINAE_PROBE_CONCEPT_concept                               \
285     CPP_PP_PROBE(~)
286 
287 /// INTERNAL ONLY
288 #define CPP_TEMPLATE_SFINAE_AUX_WHICH_(FIRST, ...)                              \
289     CPP_PP_EVAL(                                                                \
290         CPP_PP_CHECK,                                                           \
291         CPP_PP_CAT(CPP_TEMPLATE_SFINAE_PROBE_CONCEPT_, FIRST))
292 
293 /// INTERNAL ONLY
294 #define CPP_TEMPLATE_SFINAE_AUX_(...)                                           \
295     CPP_PP_CAT(                                                                 \
296         CPP_TEMPLATE_SFINAE_AUX_,                                               \
297         CPP_TEMPLATE_SFINAE_AUX_WHICH_(__VA_ARGS__,))(__VA_ARGS__)
298 
299 // A template with a requires clause
300 /// INTERNAL ONLY
301 #define CPP_TEMPLATE_SFINAE_AUX_0(...) ,                                        \
302     bool CPP_true = true,                                                       \
303     std::enable_if_t<                                                           \
304         CPP_PP_CAT(CPP_TEMPLATE_SFINAE_AUX_3_, __VA_ARGS__) &&                  \
305         CPP_BOOL(CPP_true),                                                     \
306         int> = 0>                                                               \
307     CPP_PP_IGNORE_CXX2A_COMPAT_END
308 
309 // A concept definition
310 /// INTERNAL ONLY
311 #define CPP_TEMPLATE_SFINAE_AUX_1(DECL, ...) ,                                  \
312         bool CPP_true = true,                                                   \
313         std::enable_if_t<__VA_ARGS__ && CPP_BOOL(CPP_true), int> = 0>           \
314     auto CPP_CONCEPT_NAME_(DECL)(                                               \
315         ::concepts::detail::tag<CPP_CONCEPT_PARAMS_(DECL)>*)                    \
316         -> char(&)[1];                                                          \
317     auto CPP_CONCEPT_NAME_(DECL)(...) -> char(&)[2]                             \
318     CPP_PP_IGNORE_CXX2A_COMPAT_END
319 
320 /// INTERNAL ONLY
321 #define CPP_CONCEPT_NAME_(DECL)                                                 \
322     CPP_PP_EVAL(                                                                \
323         CPP_PP_CAT,                                                             \
324         CPP_PP_EVAL(CPP_PP_FIRST, CPP_EAT_CONCEPT_(DECL)), _concept_)
325 
326 /// INTERNAL ONLY
327 #define CPP_CONCEPT_PARAMS_(DECL)                                               \
328     CPP_PP_EVAL(CPP_PP_SECOND, CPP_EAT_CONCEPT_(DECL))
329 
330 /// INTERNAL ONLY
331 #define CPP_EAT_CONCEPT_(DECL)                                                  \
332     CPP_PP_CAT(CPP_EAT_CONCEPT_, DECL)
333 
334 /// INTERNAL ONLY
335 #define CPP_EAT_CONCEPT_concept
336 
337 #define CPP_and_sfinae                                                          \
338     && CPP_BOOL(CPP_true), int> = 0, std::enable_if_t<
339 
340 #define CPP_template_def_sfinae(...)                                            \
341     template<__VA_ARGS__ CPP_TEMPLATE_DEF_SFINAE_AUX_
342 
343 /// INTERNAL ONLY
344 #define CPP_TEMPLATE_DEF_SFINAE_AUX_(...) ,                                     \
345     bool CPP_true,                                                              \
346     std::enable_if_t<                                                           \
347         CPP_PP_CAT(CPP_TEMPLATE_SFINAE_AUX_3_, __VA_ARGS__) &&                  \
348         CPP_BOOL(CPP_true),                                                     \
349         int>>
350 
351 #define CPP_and_sfinae_def                                                      \
352     && CPP_BOOL(CPP_true), int>, std::enable_if_t<
353 
354 /// INTERNAL ONLY
355 #define CPP_TEMPLATE_SFINAE_AUX_3_requires
356 
357 #define CPP_member_sfinae                                                       \
358     CPP_broken_friend_member
359 
360 #define CPP_ctor_sfinae(TYPE)                                                   \
361     CPP_PP_IGNORE_CXX2A_COMPAT_BEGIN                                            \
362     TYPE CPP_CTOR_SFINAE_IMPL_1_
363 
364 /// INTERNAL ONLY
365 #define CPP_CTOR_SFINAE_IMPL_1_(...)                                            \
366     (__VA_ARGS__                                                                \
367         CPP_PP_COMMA_IIF(                                                       \
368             CPP_PP_NOT(CPP_PP_IS_NOT_EMPTY(__VA_ARGS__)))                       \
369     CPP_CTOR_SFINAE_REQUIRES
370 
371 /// INTERNAL ONLY
372 #define CPP_CTOR_SFINAE_PROBE_NOEXCEPT_noexcept                                 \
373     CPP_PP_PROBE(~)
374 
375 /// INTERNAL ONLY
376 #define CPP_CTOR_SFINAE_MAKE_PROBE(FIRST,...)                                   \
377     CPP_PP_CAT(CPP_CTOR_SFINAE_PROBE_NOEXCEPT_, FIRST)
378 
379 /// INTERNAL ONLY
380 #define CPP_CTOR_SFINAE_REQUIRES(...)                                           \
381     CPP_PP_CAT(                                                                 \
382         CPP_CTOR_SFINAE_REQUIRES_,                                              \
383         CPP_PP_EVAL(                                                            \
384             CPP_PP_CHECK,                                                       \
385             CPP_CTOR_SFINAE_MAKE_PROBE(__VA_ARGS__,)))(__VA_ARGS__)
386 
387 // No noexcept-clause:
388 /// INTERNAL ONLY
389 #define CPP_CTOR_SFINAE_REQUIRES_0(...)                                         \
390     std::enable_if_t<                                                           \
391         CPP_PP_CAT(CPP_TEMPLATE_SFINAE_AUX_3_, __VA_ARGS__) && CPP_TRUE_FN,     \
392         ::concepts::detail::Nil                                                 \
393     > = {})                                                                     \
394     CPP_PP_IGNORE_CXX2A_COMPAT_END
395 
396 // Yes noexcept-clause:
397 /// INTERNAL ONLY
398 #define CPP_CTOR_SFINAE_REQUIRES_1(...)                                         \
399     std::enable_if_t<                                                           \
400         CPP_PP_EVAL(CPP_PP_CAT,                                                 \
401             CPP_TEMPLATE_SFINAE_AUX_3_,                                         \
402             CPP_PP_CAT(CPP_CTOR_SFINAE_EAT_NOEXCEPT_, __VA_ARGS__)) && CPP_TRUE_FN,\
403         ::concepts::detail::Nil                                                 \
404     > = {})                                                                     \
405     CPP_PP_EXPAND(CPP_PP_CAT(CPP_CTOR_SFINAE_SHOW_NOEXCEPT_, __VA_ARGS__)))
406 
407 /// INTERNAL ONLY
408 #define CPP_CTOR_SFINAE_EAT_NOEXCEPT_noexcept(...)
409 
410 /// INTERNAL ONLY
411 #define CPP_CTOR_SFINAE_SHOW_NOEXCEPT_noexcept(...)                             \
412     noexcept(__VA_ARGS__)                                                       \
413     CPP_PP_IGNORE_CXX2A_COMPAT_END                                              \
414     CPP_PP_EAT CPP_PP_LPAREN
415 
416 #ifdef CPP_DOXYGEN_INVOKED
417 #define CPP_broken_friend_ret(...)                                              \
418     __VA_ARGS__ CPP_PP_EXPAND
419 
420 #else // ^^^ CPP_DOXYGEN_INVOKED / not CPP_DOXYGEN_INVOKED vvv
421 #define CPP_broken_friend_ret(...)                                              \
422     ::concepts::return_t<                                                       \
423         __VA_ARGS__,                                                            \
424         std::enable_if_t<CPP_BROKEN_FRIEND_RETURN_TYPE_AUX_
425 
426 /// INTERNAL ONLY
427 #define CPP_BROKEN_FRIEND_RETURN_TYPE_AUX_(...)                                 \
428     CPP_BROKEN_FRIEND_RETURN_TYPE_AUX_3_(CPP_PP_CAT(                            \
429         CPP_TEMPLATE_AUX_2_, __VA_ARGS__))
430 
431 /// INTERNAL ONLY
432 #define CPP_TEMPLATE_AUX_2_requires
433 
434 /// INTERNAL ONLY
435 #define CPP_BROKEN_FRIEND_RETURN_TYPE_AUX_3_(...)                               \
436     (__VA_ARGS__ && CPP_TRUE_FN)>>
437 
438 #ifdef CPP_WORKAROUND_MSVC_779763
439 #define CPP_broken_friend_member                                                \
440     template<::concepts::detail::CPP_true_t const &CPP_true_fn =                \
441         ::concepts::detail::CPP_true_fn_>
442 
443 #else // ^^^ workaround / no workaround vvv
444 #define CPP_broken_friend_member                                                \
445     template<bool (&CPP_true_fn)(::concepts::detail::xNil) =                    \
446         ::concepts::detail::CPP_true_fn>
447 
448 #endif // CPP_WORKAROUND_MSVC_779763
449 #endif
450 
451 #if CPP_CXX_CONCEPTS
452 #define CPP_requires(NAME, REQS)                                                \
453 CPP_concept CPP_PP_CAT(NAME, _requires_) =                                      \
454     CPP_PP_CAT(CPP_REQUIRES_, REQS)
455 
456 #define CPP_requires_ref(NAME, ...)                                             \
457     CPP_PP_CAT(NAME, _requires_)<__VA_ARGS__>
458 
459 /// INTERNAL ONLY
460 #define CPP_REQUIRES_requires(...)                                              \
461     requires(__VA_ARGS__) CPP_REQUIRES_AUX_
462 
463 /// INTERNAL ONLY
464 #define CPP_REQUIRES_AUX_(...)                                                  \
465     { __VA_ARGS__; }
466 
467 #else
468 #define CPP_requires(NAME, REQS)                                                \
469     auto CPP_PP_CAT(NAME, _requires_test_)                                      \
470     CPP_REQUIRES_AUX_(NAME, CPP_REQUIRES_ ## REQS)
471 
472 #define CPP_requires_ref(NAME, ...)                                             \
473     (1u == sizeof(CPP_PP_CAT(NAME, _requires_)(                                 \
474         (::concepts::detail::tag<__VA_ARGS__>*)nullptr)))
475 
476 /// INTERNAL ONLY
477 #define CPP_REQUIRES_requires(...)                                              \
478     (__VA_ARGS__) -> decltype CPP_REQUIRES_RETURN_
479 
480 /// INTERNAL ONLY
481 #define CPP_REQUIRES_RETURN_(...) (__VA_ARGS__, void()) {}
482 
483 /// INTERNAL ONLY
484 #define CPP_REQUIRES_AUX_(NAME, ...)                                            \
485     __VA_ARGS__                                                                 \
486     template<typename... As>                                                    \
487     auto CPP_PP_CAT(NAME, _requires_)(                                          \
488         ::concepts::detail::tag<As...> *,                                       \
489         decltype(&CPP_PP_CAT(NAME, _requires_test_)<As...>) = nullptr)          \
490         -> char(&)[1];                                                          \
491     auto CPP_PP_CAT(NAME, _requires_)(...) -> char(&)[2]
492 
493 #endif
494 
495 #if CPP_CXX_CONCEPTS
496 
497 #if defined(CPP_DOXYGEN_INVOKED) && CPP_DOXYGEN_INVOKED
498 #define CPP_ret(...)                                                            \
499     __VA_ARGS__ CPP_RET_AUX_
500 #define CPP_RET_AUX_(...) __VA_ARGS__ `
501 #else
502 #define CPP_ret(...)                                                            \
503     __VA_ARGS__ CPP_PP_EXPAND
504 #endif
505 
506 #else
507 #define CPP_ret                                                                 \
508     CPP_broken_friend_ret
509 
510 #endif
511 
512 ////////////////////////////////////////////////////////////////////////////////
513 // CPP_fun
514 #if CPP_CXX_CONCEPTS
515 
516 #if defined(CPP_DOXYGEN_INVOKED) && CPP_DOXYGEN_INVOKED
517 /// INTERNAL ONLY
518 #define CPP_FUN_IMPL_1_(...)                                                    \
519     (__VA_ARGS__)                                                               \
520     CPP_FUN_IMPL_2_
521 #define CPP_FUN_IMPL_2_(...)                                                    \
522     __VA_ARGS__ `
523 #else
524 /// INTERNAL ONLY
525 #define CPP_FUN_IMPL_1_(...)                                                    \
526     (__VA_ARGS__)                                                               \
527     CPP_PP_EXPAND
528 #endif
529 
530 #define CPP_fun(X) X CPP_FUN_IMPL_1_
531 #else
532 /// INTERNAL ONLY
533 #define CPP_FUN_IMPL_1_(...)                                                    \
534     (__VA_ARGS__                                                                \
535         CPP_PP_COMMA_IIF(                                                       \
536             CPP_PP_NOT(CPP_PP_IS_NOT_EMPTY(__VA_ARGS__)))                       \
537     CPP_FUN_IMPL_REQUIRES
538 
539 /// INTERNAL ONLY
540 #define CPP_FUN_IMPL_REQUIRES(...)                                              \
541     CPP_PP_EVAL2_(                                                              \
542         CPP_FUN_IMPL_SELECT_CONST_,                                             \
543         (__VA_ARGS__,)                                                          \
544     )(__VA_ARGS__)
545 
546 /// INTERNAL ONLY
547 #define CPP_FUN_IMPL_SELECT_CONST_(MAYBE_CONST, ...)                            \
548     CPP_PP_CAT(CPP_FUN_IMPL_SELECT_CONST_,                                      \
549         CPP_PP_EVAL(CPP_PP_CHECK, CPP_PP_CAT(                                   \
550             CPP_PP_PROBE_CONST_PROBE_, MAYBE_CONST)))
551 
552 /// INTERNAL ONLY
553 #define CPP_PP_PROBE_CONST_PROBE_const CPP_PP_PROBE(~)
554 
555 /// INTERNAL ONLY
556 #define CPP_FUN_IMPL_SELECT_CONST_1(...)                                        \
557     CPP_PP_EVAL(                                                                \
558         CPP_FUN_IMPL_SELECT_CONST_NOEXCEPT_,                                    \
559         CPP_PP_CAT(CPP_FUN_IMPL_EAT_CONST_, __VA_ARGS__),)(                     \
560         CPP_PP_CAT(CPP_FUN_IMPL_EAT_CONST_, __VA_ARGS__))
561 
562 /// INTERNAL ONLY
563 #define CPP_FUN_IMPL_SELECT_CONST_NOEXCEPT_(MAYBE_NOEXCEPT, ...)                \
564     CPP_PP_CAT(CPP_FUN_IMPL_SELECT_CONST_NOEXCEPT_,                             \
565         CPP_PP_EVAL2(CPP_PP_CHECK, CPP_PP_CAT(                                  \
566             CPP_PP_PROBE_NOEXCEPT_PROBE_, MAYBE_NOEXCEPT)))
567 
568 /// INTERNAL ONLY
569 #define CPP_PP_PROBE_NOEXCEPT_PROBE_noexcept CPP_PP_PROBE(~)
570 
571 /// INTERNAL ONLY
572 #define CPP_FUN_IMPL_SELECT_CONST_NOEXCEPT_0(...)                               \
573     std::enable_if_t<                                                           \
574         CPP_PP_EVAL(                                                            \
575             CPP_PP_CAT,                                                         \
576             CPP_FUN_IMPL_EAT_REQUIRES_,                                         \
577             __VA_ARGS__) && CPP_TRUE_FN,                                           \
578         ::concepts::detail::Nil                                                 \
579     > = {}) const                                                               \
580     CPP_PP_IGNORE_CXX2A_COMPAT_END
581 
582 /// INTERNAL ONLY
583 #define CPP_FUN_IMPL_SELECT_CONST_NOEXCEPT_1(...)                               \
584     std::enable_if_t<                                                           \
585         CPP_PP_EVAL(                                                            \
586             CPP_PP_CAT,                                                         \
587             CPP_FUN_IMPL_EAT_REQUIRES_,                                         \
588             CPP_PP_CAT(CPP_FUN_IMPL_EAT_NOEXCEPT_, __VA_ARGS__)) && CPP_TRUE_FN,   \
589         ::concepts::detail::Nil                                                 \
590     > = {}) const                                                               \
591     CPP_PP_EXPAND(CPP_PP_CAT(CPP_FUN_IMPL_SHOW_NOEXCEPT_, __VA_ARGS__)))
592 
593 /// INTERNAL ONLY
594 #define CPP_FUN_IMPL_EAT_NOEXCEPT_noexcept(...)
595 
596 /// INTERNAL ONLY
597 #define CPP_FUN_IMPL_SHOW_NOEXCEPT_noexcept(...)                                \
598     noexcept(__VA_ARGS__) CPP_PP_IGNORE_CXX2A_COMPAT_END                        \
599     CPP_PP_EAT CPP_PP_LPAREN
600 
601 /// INTERNAL ONLY
602 #define CPP_FUN_IMPL_SELECT_CONST_0(...)                                        \
603     CPP_PP_EVAL_(                                                               \
604         CPP_FUN_IMPL_SELECT_NONCONST_NOEXCEPT_,                                 \
605         (__VA_ARGS__,)                                                          \
606     )(__VA_ARGS__)
607 
608 /// INTERNAL ONLY
609 #define CPP_FUN_IMPL_SELECT_NONCONST_NOEXCEPT_(MAYBE_NOEXCEPT, ...)             \
610     CPP_PP_CAT(CPP_FUN_IMPL_SELECT_NONCONST_NOEXCEPT_,                          \
611           CPP_PP_EVAL2(CPP_PP_CHECK, CPP_PP_CAT(                                \
612             CPP_PP_PROBE_NOEXCEPT_PROBE_, MAYBE_NOEXCEPT)))
613 
614 /// INTERNAL ONLY
615 #define CPP_FUN_IMPL_SELECT_NONCONST_NOEXCEPT_0(...)                            \
616     std::enable_if_t<                                                           \
617         CPP_PP_CAT(CPP_FUN_IMPL_EAT_REQUIRES_, __VA_ARGS__) && CPP_TRUE_FN,        \
618         ::concepts::detail::Nil                                                 \
619     > = {})                                                                     \
620     CPP_PP_IGNORE_CXX2A_COMPAT_END
621 
622 /// INTERNAL ONLY
623 #define CPP_FUN_IMPL_SELECT_NONCONST_NOEXCEPT_1(...)                            \
624     std::enable_if_t<                                                           \
625         CPP_PP_EVAL(                                                            \
626             CPP_PP_CAT,                                                         \
627             CPP_FUN_IMPL_EAT_REQUIRES_,                                         \
628             CPP_PP_CAT(CPP_FUN_IMPL_EAT_NOEXCEPT_, __VA_ARGS__)                 \
629         ) && CPP_TRUE_FN,                                                          \
630         ::concepts::detail::Nil                                                 \
631     > = {})                                                                     \
632     CPP_PP_EXPAND(CPP_PP_CAT(CPP_FUN_IMPL_SHOW_NOEXCEPT_, __VA_ARGS__)))
633 
634 /// INTERNAL ONLY
635 #define CPP_FUN_IMPL_EAT_CONST_const
636 
637 /// INTERNAL ONLY
638 #define CPP_FUN_IMPL_EAT_REQUIRES_requires
639 
640 ////////////////////////////////////////////////////////////////////////////////
641 // CPP_fun
642 // Usage:
643 //   template <typename A, typename B>
644 //   void CPP_fun(foo)(A a, B b)([const]opt [noexcept(true)]opt
645 //       requires Concept1<A> && Concept2<B>)
646 //   {}
647 //
648 // Note: This macro cannot be used when the last function argument is a
649 //       parameter pack.
650 #define CPP_fun(X) CPP_PP_IGNORE_CXX2A_COMPAT_BEGIN X CPP_FUN_IMPL_1_
651 #endif
652 
653 ////////////////////////////////////////////////////////////////////////////////
654 // CPP_auto_fun
655 // Usage:
656 //   template <typename A, typename B>
657 //   auto CPP_auto_fun(foo)(A a, B b)([const]opt [noexcept(cond)]opt)opt
658 //   (
659 //       return a + b
660 //   )
661 #define CPP_auto_fun(X) X CPP_AUTO_FUN_IMPL_
662 
663 /// INTERNAL ONLY
664 #define CPP_AUTO_FUN_IMPL_(...) (__VA_ARGS__) CPP_AUTO_FUN_RETURNS_
665 
666 /// INTERNAL ONLY
667 #define CPP_AUTO_FUN_RETURNS_(...)                                              \
668     CPP_PP_EVAL2_(                                                              \
669         CPP_AUTO_FUN_SELECT_RETURNS_,                                           \
670         (__VA_ARGS__,)                                                          \
671     )(__VA_ARGS__)
672 
673 /// INTERNAL ONLY
674 #define CPP_AUTO_FUN_SELECT_RETURNS_(MAYBE_CONST, ...)                          \
675     CPP_PP_CAT(CPP_AUTO_FUN_RETURNS_CONST_,                                     \
676         CPP_PP_EVAL(CPP_PP_CHECK, CPP_PP_CAT(                                   \
677             CPP_PP_PROBE_CONST_MUTABLE_PROBE_, MAYBE_CONST)))
678 
679 /// INTERNAL ONLY
680 #define CPP_PP_PROBE_CONST_MUTABLE_PROBE_const CPP_PP_PROBE_N(~, 1)
681 
682 /// INTERNAL ONLY
683 #define CPP_PP_PROBE_CONST_MUTABLE_PROBE_mutable CPP_PP_PROBE_N(~, 2)
684 
685 /// INTERNAL ONLY
686 #define CPP_PP_EAT_MUTABLE_mutable
687 
688 /// INTERNAL ONLY
689 #define CPP_AUTO_FUN_RETURNS_CONST_2(...)                                       \
690     CPP_PP_CAT(CPP_PP_EAT_MUTABLE_, __VA_ARGS__) CPP_AUTO_FUN_RETURNS_CONST_0
691 
692 /// INTERNAL ONLY
693 #define CPP_AUTO_FUN_RETURNS_CONST_1(...)                                       \
694     __VA_ARGS__ CPP_AUTO_FUN_RETURNS_CONST_0
695 
696 /// INTERNAL ONLY
697 #define CPP_AUTO_FUN_RETURNS_CONST_0(...)                                       \
698     CPP_PP_EVAL(CPP_AUTO_FUN_DECLTYPE_NOEXCEPT_,                                \
699         CPP_PP_CAT(CPP_AUTO_FUN_RETURNS_, __VA_ARGS__))
700 
701 /// INTERNAL ONLY
702 #define CPP_AUTO_FUN_RETURNS_return
703 
704 #ifdef __cpp_guaranteed_copy_elision
705 /// INTERNAL ONLY
706 #define CPP_AUTO_FUN_DECLTYPE_NOEXCEPT_(...)                                    \
707     noexcept(noexcept(__VA_ARGS__)) -> decltype(__VA_ARGS__)                    \
708     { return (__VA_ARGS__); }
709 
710 #else
711 /// INTERNAL ONLY
712 #define CPP_AUTO_FUN_DECLTYPE_NOEXCEPT_(...)                                    \
713     noexcept(noexcept(decltype(__VA_ARGS__)(__VA_ARGS__))) ->                   \
714     decltype(__VA_ARGS__)                                                       \
715     { return (__VA_ARGS__); }
716 
717 #endif
718 
719 namespace concepts
720 {
721     template<bool B>
722     using bool_ = std::integral_constant<bool, B>;
723 
724 #if defined(__cpp_fold_expressions) && __cpp_fold_expressions >= 201603
725     template<bool...Bs>
726     CPP_INLINE_VAR constexpr bool and_v = (Bs &&...);
727 
728     template<bool...Bs>
729     CPP_INLINE_VAR constexpr bool or_v = (Bs ||...);
730 #else
731     namespace detail
732     {
733         template<bool...>
734         struct bools;
735     } // namespace detail
736 
737     template<bool...Bs>
738     CPP_INLINE_VAR constexpr bool and_v =
739         META_IS_SAME(detail::bools<Bs..., true>, detail::bools<true, Bs...>);
740 
741     template<bool...Bs>
742     CPP_INLINE_VAR constexpr bool or_v =
743         !META_IS_SAME(detail::bools<Bs..., false>, detail::bools<false, Bs...>);
744 #endif
745 
746     template<typename>
747     struct return_t_
748     {
749         template<typename T>
750         using invoke = T;
751     };
752 
753     template<typename T, typename EnableIf>
754     using return_t = meta::invoke<return_t_<EnableIf>, T>;
755 
756     namespace detail
757     {
758         struct ignore
759         {
760             template<class... Args>
ignoreconcepts::detail::ignore761             constexpr ignore(Args&&...) noexcept {}
762         };
763 
764         template<class>
true_()765         constexpr bool true_()
766         {
767             return true;
768         }
769 
770         template<typename...>
771         struct tag;
772 
773         template<typename T>
774         CPP_INLINE_VAR constexpr T instance_ = T{};
775 
776         template<typename>
requires_()777         constexpr bool requires_()
778         {
779             return true;
780         }
781 
782         struct Nil
783         {};
784 
785 #ifdef CPP_WORKAROUND_MSVC_779763
786         enum class xNil {};
787 
788         struct CPP_true_t
789         {
operator ()concepts::detail::CPP_true_t790             constexpr bool operator()(Nil) const noexcept
791             {
792                 return true;
793             }
operator ()concepts::detail::CPP_true_t794             constexpr bool operator()(xNil) const noexcept
795             {
796                 return true;
797             }
798         };
799 
800         CPP_INLINE_VAR constexpr CPP_true_t CPP_true_fn_ {};
801 
CPP_true_fn(xNil)802         constexpr bool CPP_true_fn(xNil)
803         {
804             return true;
805         }
806 #else
807         using xNil = Nil;
808 #endif
809 
CPP_true_fn(Nil)810         constexpr bool CPP_true_fn(Nil)
811         {
812             return true;
813         }
814     } // namespace detail
815 
816 #if defined(__clang__) || defined(_MSC_VER)
817     template<bool B>
requires_()818     std::enable_if_t<B> requires_()
819     {}
820 #else
821     template<bool B>
822     CPP_INLINE_VAR constexpr std::enable_if_t<B, int> requires_ = 0;
823 #endif
824 
825     inline namespace defs
826     {
827         ////////////////////////////////////////////////////////////////////////
828         // Utility concepts
829         ////////////////////////////////////////////////////////////////////////
830 
831         template<bool B>
832         CPP_concept is_true = B;
833 
834         template<typename... Args>
835         CPP_concept type = true;
836 
837         template<class T, template<typename...> class Trait, typename... Args>
838         CPP_concept satisfies =
839             static_cast<bool>(Trait<T, Args...>::type::value);
840 
841         ////////////////////////////////////////////////////////////////////////
842         // Core language concepts
843         ////////////////////////////////////////////////////////////////////////
844 
845         template<typename A, typename B>
846         CPP_concept same_as =
847             META_IS_SAME(A, B) && META_IS_SAME(B, A);
848 
849         /// \cond
850         template<typename A, typename B>
851         CPP_concept not_same_as_ =
852             (!same_as<remove_cvref_t<A>, remove_cvref_t<B>>);
853 
854         // Workaround bug in the Standard Library:
855         // From cannot be an incomplete class type despite that
856         // is_convertible<X, Y> should be equivalent to is_convertible<X&&, Y>
857         // in such a case.
858         template<typename From, typename To>
859         CPP_concept implicitly_convertible_to =
860             std::is_convertible<std::add_rvalue_reference_t<From>, To>::value;
861 
862         template<typename From, typename To>
863         CPP_requires(explicitly_convertible_to_,
864             requires(From(*from)()) //
865             (
866                 static_cast<To>(from())
867             ));
868         template<typename From, typename To>
869         CPP_concept explicitly_convertible_to =
870             CPP_requires_ref(concepts::explicitly_convertible_to_, From, To);
871         /// \endcond
872 
873         template<typename From, typename To>
874         CPP_concept convertible_to =
875             implicitly_convertible_to<From, To> &&
876             explicitly_convertible_to<From, To>;
877 
878         CPP_template(typename T, typename U)(
879         concept (derived_from_)(T, U),
880             convertible_to<T const volatile *, U const volatile *>
881         );
882         template<typename T, typename U>
883         CPP_concept derived_from =
884             META_IS_BASE_OF(U, T) &&
885             CPP_concept_ref(concepts::derived_from_, T, U);
886 
887         CPP_template(typename T, typename U)(
888         concept (common_reference_with_)(T, U),
889             same_as<common_reference_t<T, U>, common_reference_t<U, T>> CPP_and
890             convertible_to<T, common_reference_t<T, U>> CPP_and
891             convertible_to<U, common_reference_t<T, U>>
892         );
893         template<typename T, typename U>
894         CPP_concept common_reference_with =
895             CPP_concept_ref(concepts::common_reference_with_, T, U);
896 
897         CPP_template(typename T, typename U)(
898         concept (common_with_)(T, U),
899             same_as<common_type_t<T, U>, common_type_t<U, T>> CPP_and
900             convertible_to<T, common_type_t<T, U>> CPP_and
901             convertible_to<U, common_type_t<T, U>> CPP_and
902             common_reference_with<
903                 std::add_lvalue_reference_t<T const>,
904                 std::add_lvalue_reference_t<U const>> CPP_and
905             common_reference_with<
906                 std::add_lvalue_reference_t<common_type_t<T, U>>,
907                 common_reference_t<
908                     std::add_lvalue_reference_t<T const>,
909                     std::add_lvalue_reference_t<U const>>>
910         );
911         template<typename T, typename U>
912         CPP_concept common_with =
913             CPP_concept_ref(concepts::common_with_, T, U);
914 
915         template<typename T>
916         CPP_concept integral =
917             std::is_integral<T>::value;
918 
919         template<typename T>
920         CPP_concept signed_integral =
921             integral<T> &&
922             std::is_signed<T>::value;
923 
924         template<typename T>
925         CPP_concept unsigned_integral =
926             integral<T> &&
927             !signed_integral<T>;
928 
929         template<typename T, typename U>
930         CPP_requires(assignable_from_,
931             requires(T t, U && u) //
932             (
933                 t = (U &&) u,
934                 requires_<same_as<T, decltype(t = (U &&) u)>>
935             ));
936         template<typename T, typename U>
937         CPP_concept assignable_from =
938             std::is_lvalue_reference<T>::value &&
939             common_reference_with<detail::as_cref_t<T>, detail::as_cref_t<U>> &&
940             CPP_requires_ref(defs::assignable_from_, T, U);
941 
942         template<typename T>
943         CPP_requires(swappable_,
944             requires(T & t, T & u) //
945             (
946                 concepts::swap(t, u)
947             ));
948         template<typename T>
949         CPP_concept swappable =
950             CPP_requires_ref(defs::swappable_, T);
951 
952         template<typename T, typename U>
953         CPP_requires(swappable_with_,
954             requires(T && t, U && u) //
955             (
956                 concepts::swap((T &&) t, (T &&) t),
957                 concepts::swap((U &&) u, (U &&) u),
958                 concepts::swap((U &&) u, (T &&) t),
959                 concepts::swap((T &&) t, (U &&) u)
960             ));
961         template<typename T, typename U>
962         CPP_concept swappable_with =
963             common_reference_with<detail::as_cref_t<T>, detail::as_cref_t<U>> &&
964             CPP_requires_ref(defs::swappable_with_, T, U);
965 
966     }  // inline namespace defs
967 
968     namespace detail
969     {
970         template<typename T>
971         CPP_concept boolean_testable_impl_ = convertible_to<T, bool>;
972 
973         template<typename T>
974         CPP_requires(boolean_testable_frag_,
975             requires(T && t) //
976             (
977                 !(T&&) t,
978                 concepts::requires_<boolean_testable_impl_<decltype(!(T&&) t)>>
979             ));
980 
981         template<typename T>
982         CPP_concept boolean_testable_ =
983             CPP_requires_ref(boolean_testable_frag_, T) &&
984             boolean_testable_impl_<T>;
985 
986         CPP_DIAGNOSTIC_PUSH
987         CPP_DIAGNOSTIC_IGNORE_FLOAT_EQUAL
988 
989         template<typename T, typename U>
990         CPP_requires(weakly_equality_comparable_with_frag_,
991             requires(detail::as_cref_t<T> t, detail::as_cref_t<U> u) //
992             (
993                 concepts::requires_<boolean_testable_<decltype(t == u)>>,
994                 concepts::requires_<boolean_testable_<decltype(t != u)>>,
995                 concepts::requires_<boolean_testable_<decltype(u == t)>>,
996                 concepts::requires_<boolean_testable_<decltype(u != t)>>
997             ));
998         template<typename T, typename U>
999         CPP_concept weakly_equality_comparable_with_ =
1000             CPP_requires_ref(weakly_equality_comparable_with_frag_, T, U);
1001 
1002         template<typename T, typename U>
1003         CPP_requires(partially_ordered_with_frag_,
1004             requires(detail::as_cref_t<T>& t, detail::as_cref_t<U>& u) //
1005             (
1006                 concepts::requires_<boolean_testable_<decltype(t < u)>>,
1007                 concepts::requires_<boolean_testable_<decltype(t > u)>>,
1008                 concepts::requires_<boolean_testable_<decltype(t <= u)>>,
1009                 concepts::requires_<boolean_testable_<decltype(t >= u)>>,
1010                 concepts::requires_<boolean_testable_<decltype(u < t)>>,
1011                 concepts::requires_<boolean_testable_<decltype(u > t)>>,
1012                 concepts::requires_<boolean_testable_<decltype(u <= t)>>,
1013                 concepts::requires_<boolean_testable_<decltype(u >= t)>>
1014             ));
1015         template<typename T, typename U>
1016         CPP_concept partially_ordered_with_ =
1017             CPP_requires_ref(partially_ordered_with_frag_, T, U);
1018 
1019         CPP_DIAGNOSTIC_POP
1020     } // namespace detail
1021 
1022     inline namespace defs
1023     {
1024         ////////////////////////////////////////////////////////////////////////
1025         // Comparison concepts
1026         ////////////////////////////////////////////////////////////////////////
1027 
1028         template<typename T>
1029         CPP_concept equality_comparable =
1030             detail::weakly_equality_comparable_with_<T, T>;
1031 
1032         CPP_template(typename T, typename U)(
1033         concept (equality_comparable_with_)(T, U),
1034             equality_comparable<
1035                 common_reference_t<detail::as_cref_t<T>, detail::as_cref_t<U>>>
1036         );
1037         template<typename T, typename U>
1038         CPP_concept equality_comparable_with =
1039             equality_comparable<T> &&
1040             equality_comparable<U> &&
1041             detail::weakly_equality_comparable_with_<T, U> &&
1042             common_reference_with<detail::as_cref_t<T>, detail::as_cref_t<U>> &&
1043             CPP_concept_ref(concepts::equality_comparable_with_, T, U);
1044 
1045         template<typename T>
1046         CPP_concept totally_ordered =
1047             equality_comparable<T> &&
1048             detail::partially_ordered_with_<T, T>;
1049 
1050         CPP_template(typename T, typename U)(
1051         concept (totally_ordered_with_)(T, U),
1052             totally_ordered<
1053                 common_reference_t<
1054                     detail::as_cref_t<T>,
1055                     detail::as_cref_t<U>>> CPP_and
1056             detail::partially_ordered_with_<T, U>);
1057 
1058         template<typename T, typename U>
1059         CPP_concept totally_ordered_with =
1060             totally_ordered<T> &&
1061             totally_ordered<U> &&
1062             equality_comparable_with<T, U> &&
1063             CPP_concept_ref(concepts::totally_ordered_with_, T, U);
1064 
1065         ////////////////////////////////////////////////////////////////////////
1066         // Object concepts
1067         ////////////////////////////////////////////////////////////////////////
1068 
1069         template<typename T>
1070         CPP_concept destructible =
1071             std::is_nothrow_destructible<T>::value;
1072 
1073         template<typename T, typename... Args>
1074         CPP_concept constructible_from =
1075             destructible<T> &&
1076             META_IS_CONSTRUCTIBLE(T, Args...);
1077 
1078         template<typename T>
1079         CPP_concept default_constructible =
1080             constructible_from<T>;
1081 
1082         template<typename T>
1083         CPP_concept move_constructible =
1084             constructible_from<T, T> &&
1085             convertible_to<T, T>;
1086 
1087         CPP_template(typename T)(
1088         concept (copy_constructible_)(T),
1089             constructible_from<T, T &> &&
1090             constructible_from<T, T const &> &&
1091             constructible_from<T, T const> &&
1092             convertible_to<T &, T> &&
1093             convertible_to<T const &, T> &&
1094             convertible_to<T const, T>);
1095         template<typename T>
1096         CPP_concept copy_constructible =
1097             move_constructible<T> &&
1098             CPP_concept_ref(concepts::copy_constructible_, T);
1099 
1100         CPP_template(typename T)(
1101         concept (move_assignable_)(T),
1102             assignable_from<T &, T>
1103         );
1104         template<typename T>
1105         CPP_concept movable =
1106             std::is_object<T>::value &&
1107             move_constructible<T> &&
1108             CPP_concept_ref(concepts::move_assignable_, T) &&
1109             swappable<T>;
1110 
1111         CPP_template(typename T)(
1112         concept (copy_assignable_)(T),
1113             assignable_from<T &, T const &>
1114         );
1115         template<typename T>
1116         CPP_concept copyable =
1117             copy_constructible<T> &&
1118             movable<T> &&
1119             CPP_concept_ref(concepts::copy_assignable_, T);
1120 
1121         template<typename T>
1122         CPP_concept semiregular =
1123             copyable<T> &&
1124             default_constructible<T>;
1125             // Axiom: copies are independent. See Fundamentals of Generic
1126             // Programming http://www.stepanovpapers.com/DeSt98.pdf
1127 
1128         template<typename T>
1129         CPP_concept regular =
1130             semiregular<T> &&
1131             equality_comparable<T>;
1132 
1133     } // inline namespace defs
1134 } // namespace concepts
1135 
1136 #endif // RANGES_V3_UTILITY_CONCEPTS_HPP
1137