Horizon
Loading...
Searching...
No Matches
concepts.hpp
Go to the documentation of this file.
1
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>
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
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#if defined(CPP_DOXYGEN_INVOKED)
208#define CPP_template(...) template<__VA_ARGS__> CPP_TEMPLATE_EXPAND_
209#define CPP_TEMPLATE_EXPAND_(X,Y) X Y
210#else
211#define CPP_template(...) template<__VA_ARGS__ CPP_TEMPLATE_AUX_
212#endif
213#define CPP_template_def CPP_template
214#define CPP_member
215#define CPP_ctor(TYPE) TYPE CPP_CTOR_IMPL_1_
216#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 10
217#define CPP_auto_member template<typename...>
218#else
219#define CPP_auto_member
220#endif
221
223#define CPP_CTOR_IMPL_1_(...) (__VA_ARGS__) CPP_PP_EXPAND
224
226#define CPP_TEMPLATE_AUX_(...) \
227 > CPP_PP_CAT( \
228 CPP_TEMPLATE_AUX_, \
229 CPP_TEMPLATE_AUX_WHICH_(__VA_ARGS__,))(__VA_ARGS__)
230
232#define CPP_TEMPLATE_AUX_WHICH_(FIRST, ...) \
233 CPP_PP_EVAL( \
234 CPP_PP_CHECK, \
235 CPP_PP_CAT(CPP_TEMPLATE_PROBE_CONCEPT_, FIRST))
236
238#define CPP_TEMPLATE_PROBE_CONCEPT_concept \
239 CPP_PP_PROBE(~)
240
241// A template with a requires clause
243#define CPP_TEMPLATE_AUX_0(...) __VA_ARGS__
244
245// A concept definition
247#define CPP_TEMPLATE_AUX_1(DECL, ...) \
248 CPP_concept CPP_CONCEPT_NAME_(DECL) = __VA_ARGS__
249
250#if defined(CPP_DOXYGEN_INVOKED)
251#define CPP_concept_ref(NAME, ...) \
252 NAME<__VA_ARGS__>
253#else
254#define CPP_concept_ref(NAME, ...) \
255 CPP_PP_CAT(NAME, concept_)<__VA_ARGS__>
256#endif
257
258#else // ^^^^ with concepts / without concepts vvvv
259
260#define CPP_template CPP_template_sfinae
261#define CPP_template_def CPP_template_def_sfinae
262#define CPP_member CPP_member_sfinae
263#define CPP_auto_member CPP_member_sfinae
264#define CPP_ctor CPP_ctor_sfinae
265#define CPP_concept_ref(NAME, ...) \
266 (1u == sizeof(CPP_PP_CAT(NAME, concept_)( \
267 (::concepts::detail::tag<__VA_ARGS__>*)nullptr)))
268
270#define CPP_TEMPLATE_AUX_ CPP_TEMPLATE_SFINAE_AUX_
271
272#endif
273
274#define CPP_template_sfinae(...) \
275 CPP_PP_IGNORE_CXX2A_COMPAT_BEGIN \
276 template<__VA_ARGS__ CPP_TEMPLATE_SFINAE_AUX_
277
279#define CPP_TEMPLATE_SFINAE_PROBE_CONCEPT_concept \
280 CPP_PP_PROBE(~)
281
283#define CPP_TEMPLATE_SFINAE_AUX_WHICH_(FIRST, ...) \
284 CPP_PP_EVAL( \
285 CPP_PP_CHECK, \
286 CPP_PP_CAT(CPP_TEMPLATE_SFINAE_PROBE_CONCEPT_, FIRST))
287
289#define CPP_TEMPLATE_SFINAE_AUX_(...) \
290 CPP_PP_CAT( \
291 CPP_TEMPLATE_SFINAE_AUX_, \
292 CPP_TEMPLATE_SFINAE_AUX_WHICH_(__VA_ARGS__,))(__VA_ARGS__)
293
294// A template with a requires clause
296#define CPP_TEMPLATE_SFINAE_AUX_0(...) , \
297 bool CPP_true = true, \
298 std::enable_if_t< \
299 CPP_PP_CAT(CPP_TEMPLATE_SFINAE_AUX_3_, __VA_ARGS__) && \
300 CPP_BOOL(CPP_true), \
301 int> = 0> \
302 CPP_PP_IGNORE_CXX2A_COMPAT_END
303
304// A concept definition
306#define CPP_TEMPLATE_SFINAE_AUX_1(DECL, ...) , \
307 bool CPP_true = true, \
308 std::enable_if_t<__VA_ARGS__ && CPP_BOOL(CPP_true), int> = 0> \
309 auto CPP_CONCEPT_NAME_(DECL)( \
310 ::concepts::detail::tag<CPP_CONCEPT_PARAMS_(DECL)>*) \
311 -> char(&)[1]; \
312 auto CPP_CONCEPT_NAME_(DECL)(...) -> char(&)[2] \
313 CPP_PP_IGNORE_CXX2A_COMPAT_END
314
316#define CPP_CONCEPT_NAME_(DECL) \
317 CPP_PP_EVAL( \
318 CPP_PP_CAT, \
319 CPP_PP_EVAL(CPP_PP_FIRST, CPP_EAT_CONCEPT_(DECL)), concept_)
320
322#define CPP_CONCEPT_PARAMS_(DECL) \
323 CPP_PP_EVAL(CPP_PP_SECOND, CPP_EAT_CONCEPT_(DECL))
324
326#define CPP_EAT_CONCEPT_(DECL) \
327 CPP_PP_CAT(CPP_EAT_CONCEPT_, DECL)
328
330#define CPP_EAT_CONCEPT_concept
331
333#define CPP_and_sfinae \
334 && CPP_BOOL(CPP_true), int> = 0, std::enable_if_t<
335
337#define CPP_template_def_sfinae(...) \
338 template<__VA_ARGS__ CPP_TEMPLATE_DEF_SFINAE_AUX_
339
341#define CPP_TEMPLATE_DEF_SFINAE_AUX_(...) , \
342 bool CPP_true, \
343 std::enable_if_t< \
344 CPP_PP_CAT(CPP_TEMPLATE_SFINAE_AUX_3_, __VA_ARGS__) && \
345 CPP_BOOL(CPP_true), \
346 int>>
347
349#define CPP_and_sfinae_def \
350 && CPP_BOOL(CPP_true), int>, std::enable_if_t<
351
353#define CPP_TEMPLATE_SFINAE_AUX_3_requires
354
356#define CPP_member_sfinae \
357 CPP_broken_friend_member
358
360#define CPP_ctor_sfinae(TYPE) \
361 CPP_PP_IGNORE_CXX2A_COMPAT_BEGIN \
362 TYPE CPP_CTOR_SFINAE_IMPL_1_
363
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
372#define CPP_CTOR_SFINAE_PROBE_NOEXCEPT_noexcept \
373 CPP_PP_PROBE(~)
374
376#define CPP_CTOR_SFINAE_MAKE_PROBE(FIRST,...) \
377 CPP_PP_CAT(CPP_CTOR_SFINAE_PROBE_NOEXCEPT_, FIRST)
378
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:
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:
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
408#define CPP_CTOR_SFINAE_EAT_NOEXCEPT_noexcept(...)
409
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
418#define CPP_broken_friend_ret(...) \
419 __VA_ARGS__ CPP_PP_EXPAND
420
421#else // ^^^ CPP_DOXYGEN_INVOKED / not CPP_DOXYGEN_INVOKED vvv
422#define CPP_broken_friend_ret(...) \
423 ::concepts::return_t< \
424 __VA_ARGS__, \
425 std::enable_if_t<CPP_BROKEN_FRIEND_RETURN_TYPE_AUX_
426
428#define CPP_BROKEN_FRIEND_RETURN_TYPE_AUX_(...) \
429 CPP_BROKEN_FRIEND_RETURN_TYPE_AUX_3_(CPP_PP_CAT( \
430 CPP_TEMPLATE_AUX_2_, __VA_ARGS__))
431
433#define CPP_TEMPLATE_AUX_2_requires
434
436#define CPP_BROKEN_FRIEND_RETURN_TYPE_AUX_3_(...) \
437 (__VA_ARGS__ && CPP_TRUE_FN)>>
438
439#ifdef CPP_WORKAROUND_MSVC_779763
441#define CPP_broken_friend_member \
442 template<::concepts::detail::CPP_true_t const &CPP_true_fn = \
443 ::concepts::detail::CPP_true_fn_>
444
445#else // ^^^ workaround / no workaround vvv
447#define CPP_broken_friend_member \
448 template<bool (&CPP_true_fn)(::concepts::detail::xNil) = \
449 ::concepts::detail::CPP_true_fn>
450
451#endif // CPP_WORKAROUND_MSVC_779763
452#endif
453
454#if CPP_CXX_CONCEPTS
455#if defined(CPP_DOXYGEN_INVOKED)
456#define CPP_requires(NAME, REQS) \
457 concept NAME = \
458 CPP_PP_CAT(CPP_REQUIRES_, REQS)
459#define CPP_requires_ref(NAME, ...) \
460 NAME<__VA_ARGS__>
461#else
462#define CPP_requires(NAME, REQS) \
463 CPP_concept CPP_PP_CAT(NAME, requires_) = \
464 CPP_PP_CAT(CPP_REQUIRES_, REQS)
465#define CPP_requires_ref(NAME, ...) \
466 CPP_PP_CAT(NAME, requires_)<__VA_ARGS__>
467#endif
468
470#define CPP_REQUIRES_requires(...) \
471 requires(__VA_ARGS__) CPP_REQUIRES_AUX_
472
474#define CPP_REQUIRES_AUX_(...) \
475 { __VA_ARGS__; }
476
477#else
478#define CPP_requires(NAME, REQS) \
479 auto CPP_PP_CAT(NAME, requires_test_) \
480 CPP_REQUIRES_AUX_(NAME, CPP_REQUIRES_ ## REQS)
481
482#define CPP_requires_ref(NAME, ...) \
483 (1u == sizeof(CPP_PP_CAT(NAME, requires_)( \
484 (::concepts::detail::tag<__VA_ARGS__>*)nullptr)))
485
487#define CPP_REQUIRES_requires(...) \
488 (__VA_ARGS__) -> decltype CPP_REQUIRES_RETURN_
489
491#define CPP_REQUIRES_RETURN_(...) (__VA_ARGS__, void()) {}
492
494#define CPP_REQUIRES_AUX_(NAME, ...) \
495 __VA_ARGS__ \
496 template<typename... As> \
497 auto CPP_PP_CAT(NAME, requires_)( \
498 ::concepts::detail::tag<As...> *, \
499 decltype(&CPP_PP_CAT(NAME, requires_test_)<As...>) = nullptr) \
500 -> char(&)[1]; \
501 auto CPP_PP_CAT(NAME, requires_)(...) -> char(&)[2]
502
503#endif
504
505#if CPP_CXX_CONCEPTS
506#define CPP_ret(...) \
507 __VA_ARGS__ CPP_PP_EXPAND
508#else
509#define CPP_ret \
510 CPP_broken_friend_ret
511#endif
512
514// CPP_fun
515#if CPP_CXX_CONCEPTS
516
518#define CPP_FUN_IMPL_1_(...) \
519 (__VA_ARGS__) \
520 CPP_PP_EXPAND
521
522#define CPP_fun(X) X CPP_FUN_IMPL_1_
523#else
525#define CPP_FUN_IMPL_1_(...) \
526 (__VA_ARGS__ \
527 CPP_PP_COMMA_IIF( \
528 CPP_PP_NOT(CPP_PP_IS_NOT_EMPTY(__VA_ARGS__))) \
529 CPP_FUN_IMPL_REQUIRES
530
532#define CPP_FUN_IMPL_REQUIRES(...) \
533 CPP_PP_EVAL2_( \
534 CPP_FUN_IMPL_SELECT_CONST_, \
535 (__VA_ARGS__,) \
536 )(__VA_ARGS__)
537
539#define CPP_FUN_IMPL_SELECT_CONST_(MAYBE_CONST, ...) \
540 CPP_PP_CAT(CPP_FUN_IMPL_SELECT_CONST_, \
541 CPP_PP_EVAL(CPP_PP_CHECK, CPP_PP_CAT( \
542 CPP_PP_PROBE_CONST_PROBE_, MAYBE_CONST)))
543
545#define CPP_PP_PROBE_CONST_PROBE_const CPP_PP_PROBE(~)
546
548#define CPP_FUN_IMPL_SELECT_CONST_1(...) \
549 CPP_PP_EVAL( \
550 CPP_FUN_IMPL_SELECT_CONST_NOEXCEPT_, \
551 CPP_PP_CAT(CPP_FUN_IMPL_EAT_CONST_, __VA_ARGS__),)( \
552 CPP_PP_CAT(CPP_FUN_IMPL_EAT_CONST_, __VA_ARGS__))
553
555#define CPP_FUN_IMPL_SELECT_CONST_NOEXCEPT_(MAYBE_NOEXCEPT, ...) \
556 CPP_PP_CAT(CPP_FUN_IMPL_SELECT_CONST_NOEXCEPT_, \
557 CPP_PP_EVAL2(CPP_PP_CHECK, CPP_PP_CAT( \
558 CPP_PP_PROBE_NOEXCEPT_PROBE_, MAYBE_NOEXCEPT)))
559
561#define CPP_PP_PROBE_NOEXCEPT_PROBE_noexcept CPP_PP_PROBE(~)
562
564#define CPP_FUN_IMPL_SELECT_CONST_NOEXCEPT_0(...) \
565 std::enable_if_t< \
566 CPP_PP_EVAL( \
567 CPP_PP_CAT, \
568 CPP_FUN_IMPL_EAT_REQUIRES_, \
569 __VA_ARGS__) && CPP_TRUE_FN, \
570 ::concepts::detail::Nil \
571 > = {}) const \
572 CPP_PP_IGNORE_CXX2A_COMPAT_END
573
575#define CPP_FUN_IMPL_SELECT_CONST_NOEXCEPT_1(...) \
576 std::enable_if_t< \
577 CPP_PP_EVAL( \
578 CPP_PP_CAT, \
579 CPP_FUN_IMPL_EAT_REQUIRES_, \
580 CPP_PP_CAT(CPP_FUN_IMPL_EAT_NOEXCEPT_, __VA_ARGS__)) && CPP_TRUE_FN,\
581 ::concepts::detail::Nil \
582 > = {}) const \
583 CPP_PP_EXPAND(CPP_PP_CAT(CPP_FUN_IMPL_SHOW_NOEXCEPT_, __VA_ARGS__)))
584
586#define CPP_FUN_IMPL_EAT_NOEXCEPT_noexcept(...)
587
589#define CPP_FUN_IMPL_SHOW_NOEXCEPT_noexcept(...) \
590 noexcept(__VA_ARGS__) CPP_PP_IGNORE_CXX2A_COMPAT_END \
591 CPP_PP_EAT CPP_PP_LPAREN
592
594#define CPP_FUN_IMPL_SELECT_CONST_0(...) \
595 CPP_PP_EVAL_( \
596 CPP_FUN_IMPL_SELECT_NONCONST_NOEXCEPT_, \
597 (__VA_ARGS__,) \
598 )(__VA_ARGS__)
599
601#define CPP_FUN_IMPL_SELECT_NONCONST_NOEXCEPT_(MAYBE_NOEXCEPT, ...) \
602 CPP_PP_CAT(CPP_FUN_IMPL_SELECT_NONCONST_NOEXCEPT_, \
603 CPP_PP_EVAL2(CPP_PP_CHECK, CPP_PP_CAT( \
604 CPP_PP_PROBE_NOEXCEPT_PROBE_, MAYBE_NOEXCEPT)))
605
607#define CPP_FUN_IMPL_SELECT_NONCONST_NOEXCEPT_0(...) \
608 std::enable_if_t< \
609 CPP_PP_CAT(CPP_FUN_IMPL_EAT_REQUIRES_, __VA_ARGS__) && CPP_TRUE_FN, \
610 ::concepts::detail::Nil \
611 > = {}) \
612 CPP_PP_IGNORE_CXX2A_COMPAT_END
613
615#define CPP_FUN_IMPL_SELECT_NONCONST_NOEXCEPT_1(...) \
616 std::enable_if_t< \
617 CPP_PP_EVAL( \
618 CPP_PP_CAT, \
619 CPP_FUN_IMPL_EAT_REQUIRES_, \
620 CPP_PP_CAT(CPP_FUN_IMPL_EAT_NOEXCEPT_, __VA_ARGS__) \
621 ) && CPP_TRUE_FN, \
622 ::concepts::detail::Nil \
623 > = {}) \
624 CPP_PP_EXPAND(CPP_PP_CAT(CPP_FUN_IMPL_SHOW_NOEXCEPT_, __VA_ARGS__)))
625
627#define CPP_FUN_IMPL_EAT_CONST_const
628
630#define CPP_FUN_IMPL_EAT_REQUIRES_requires
631
633// CPP_fun
634// Usage:
635// template <typename A, typename B>
636// void CPP_fun(foo)(A a, B b)([const]opt [noexcept(true)]opt
637// requires Concept1<A> && Concept2<B>)
638// {}
639//
640// Note: This macro cannot be used when the last function argument is a
641// parameter pack.
642#define CPP_fun(X) CPP_PP_IGNORE_CXX2A_COMPAT_BEGIN X CPP_FUN_IMPL_1_
643#endif
644
646// CPP_auto_fun
647// Usage:
648// template <typename A, typename B>
649// auto CPP_auto_fun(foo)(A a, B b)([const]opt [noexcept(cond)]opt)opt
650// (
651// return a + b
652// )
653#define CPP_auto_fun(X) X CPP_AUTO_FUN_IMPL_
654
656#define CPP_AUTO_FUN_IMPL_(...) (__VA_ARGS__) CPP_AUTO_FUN_RETURNS_
657
659#define CPP_AUTO_FUN_RETURNS_(...) \
660 CPP_PP_EVAL2_( \
661 CPP_AUTO_FUN_SELECT_RETURNS_, \
662 (__VA_ARGS__,) \
663 )(__VA_ARGS__)
664
666#define CPP_AUTO_FUN_SELECT_RETURNS_(MAYBE_CONST, ...) \
667 CPP_PP_CAT(CPP_AUTO_FUN_RETURNS_CONST_, \
668 CPP_PP_EVAL(CPP_PP_CHECK, CPP_PP_CAT( \
669 CPP_PP_PROBE_CONST_MUTABLE_PROBE_, MAYBE_CONST)))
670
672#define CPP_PP_PROBE_CONST_MUTABLE_PROBE_const CPP_PP_PROBE_N(~, 1)
673
675#define CPP_PP_PROBE_CONST_MUTABLE_PROBE_mutable CPP_PP_PROBE_N(~, 2)
676
678#define CPP_PP_EAT_MUTABLE_mutable
679
681#define CPP_AUTO_FUN_RETURNS_CONST_2(...) \
682 CPP_PP_CAT(CPP_PP_EAT_MUTABLE_, __VA_ARGS__) CPP_AUTO_FUN_RETURNS_CONST_0
683
685#define CPP_AUTO_FUN_RETURNS_CONST_1(...) \
686 __VA_ARGS__ CPP_AUTO_FUN_RETURNS_CONST_0
687
689#define CPP_AUTO_FUN_RETURNS_CONST_0(...) \
690 CPP_PP_EVAL(CPP_AUTO_FUN_DECLTYPE_NOEXCEPT_, \
691 CPP_PP_CAT(CPP_AUTO_FUN_RETURNS_, __VA_ARGS__))
692
694#define CPP_AUTO_FUN_RETURNS_return
695
696#ifdef __cpp_guaranteed_copy_elision
698#define CPP_AUTO_FUN_DECLTYPE_NOEXCEPT_(...) \
699 noexcept(noexcept(__VA_ARGS__)) -> decltype(__VA_ARGS__) \
700 { return (__VA_ARGS__); }
701
702#else
704#define CPP_AUTO_FUN_DECLTYPE_NOEXCEPT_(...) \
705 noexcept(noexcept(decltype(__VA_ARGS__)(__VA_ARGS__))) -> \
706 decltype(__VA_ARGS__) \
707 { return (__VA_ARGS__); }
708
709#endif
710
711#if defined(CPP_DOXYGEN_INVOKED)
712#define concept(NAME) concept NAME CPP_CONCEPT_EQUALS_
713#define CPP_CONCEPT_EQUALS_(...) =
714#endif
715
716namespace concepts
717{
718 template<bool B>
719 using bool_ = std::integral_constant<bool, B>;
720
721#if defined(__cpp_fold_expressions) && __cpp_fold_expressions >= 201603
722 template<bool...Bs>
723 CPP_INLINE_VAR constexpr bool and_v = (Bs &&...);
724
725 template<bool...Bs>
726 CPP_INLINE_VAR constexpr bool or_v = (Bs ||...);
727#else
728 namespace detail
729 {
730 template<bool...>
731 struct bools;
732 } // namespace detail
733
734 template<bool...Bs>
735 CPP_INLINE_VAR constexpr bool and_v =
737
738 template<bool...Bs>
739 CPP_INLINE_VAR constexpr bool or_v =
741#endif
742
743 template<typename>
745 {
746 template<typename T>
747 using invoke = T;
748 };
749
750 template<typename T, typename EnableIf>
751 using return_t = meta::invoke<return_t_<EnableIf>, T>;
752
754 namespace detail
755 {
756 struct ignore
757 {
758 template<class... Args>
759 constexpr ignore(Args&&...) noexcept {}
760 };
761
762 template<class>
763 constexpr bool true_()
764 {
765 return true;
766 }
767
768 template<typename...>
769 struct tag;
770
771 template<typename T>
772 CPP_INLINE_VAR constexpr T instance_ = T{};
773
774 template<typename>
775 constexpr bool requires_()
776 {
777 return true;
778 }
779
780 struct Nil
781 {};
782
783#ifdef CPP_WORKAROUND_MSVC_779763
784 enum class xNil {};
785
786 struct CPP_true_t
787 {
788 constexpr bool operator()(Nil) const noexcept
789 {
790 return true;
791 }
792 constexpr bool operator()(xNil) const noexcept
793 {
794 return true;
795 }
796 };
797
798 CPP_INLINE_VAR constexpr CPP_true_t CPP_true_fn_ {};
799
800 constexpr bool CPP_true_fn(xNil)
801 {
802 return true;
803 }
804#else
805 using xNil = Nil;
806#endif
807
808 constexpr bool CPP_true_fn(Nil)
809 {
810 return true;
811 }
812 } // namespace detail
814
815#if defined(__clang__) || defined(_MSC_VER)
816 template<bool B>
817 std::enable_if_t<B> requires_()
818 {}
819#else
820 template<bool B>
821 CPP_INLINE_VAR constexpr std::enable_if_t<B, int> requires_ = 0;
822#endif
823
824 inline namespace defs
825 {
827 // Utility concepts
829
832 template<bool B>
833 CPP_concept is_true = B;
834
837 template<typename... Args>
838 CPP_concept type = true;
839
842 template<class T, template<typename...> class Trait, typename... Args>
843 CPP_concept satisfies =
844 static_cast<bool>(Trait<T, Args...>::type::value);
845
847 // Core language concepts
849
852 template<typename A, typename B>
853 CPP_concept same_as =
854 META_IS_SAME(A, B) && META_IS_SAME(B, A);
855
859 template<typename A, typename B>
860 CPP_concept not_same_as_ =
861 (!same_as<remove_cvref_t<A>, remove_cvref_t<B>>);
863
864 // Workaround bug in the Standard Library:
865 // From cannot be an incomplete class type despite that
866 // is_convertible<X, Y> should be equivalent to is_convertible<X&&, Y>
867 // in such a case.
870 template<typename From, typename To>
871 CPP_concept implicitly_convertible_to =
872 std::is_convertible<std::add_rvalue_reference_t<From>, To>::value;
873
876 template<typename From, typename To>
877 CPP_requires(explicitly_convertible_to_,
878 requires(From(*from)()) //
879 (
880 static_cast<To>(from())
881 ));
884 template<typename From, typename To>
885 CPP_concept explicitly_convertible_to =
886 CPP_requires_ref(concepts::explicitly_convertible_to_, From, To);
887
890 template<typename From, typename To>
891 CPP_concept convertible_to =
892 implicitly_convertible_to<From, To> &&
893 explicitly_convertible_to<From, To>;
894
897 CPP_template(typename T, typename U)(
898 concept (derived_from_)(T, U),
899 convertible_to<T const volatile *, U const volatile *>
900 );
903 template<typename T, typename U>
904 CPP_concept derived_from =
905 META_IS_BASE_OF(U, T) &&
906 CPP_concept_ref(concepts::derived_from_, T, U);
907
910 CPP_template(typename T, typename U)(
911 concept (common_reference_with_)(T, U),
912 same_as<common_reference_t<T, U>, common_reference_t<U, T>> CPP_and
913 convertible_to<T, common_reference_t<T, U>> CPP_and
914 convertible_to<U, common_reference_t<T, U>>
915 );
918 template<typename T, typename U>
919 CPP_concept common_reference_with =
920 CPP_concept_ref(concepts::common_reference_with_, T, U);
921
924 CPP_template(typename T, typename U)(
925 concept (common_with_)(T, U),
926 same_as<common_type_t<T, U>, common_type_t<U, T>> CPP_and
927 convertible_to<T, common_type_t<T, U>> CPP_and
928 convertible_to<U, common_type_t<T, U>> CPP_and
929 common_reference_with<
930 std::add_lvalue_reference_t<T const>,
931 std::add_lvalue_reference_t<U const>> CPP_and
932 common_reference_with<
933 std::add_lvalue_reference_t<common_type_t<T, U>>,
934 common_reference_t<
935 std::add_lvalue_reference_t<T const>,
936 std::add_lvalue_reference_t<U const>>>
937 );
940 template<typename T, typename U>
941 CPP_concept common_with =
942 CPP_concept_ref(concepts::common_with_, T, U);
943
946 template<typename T>
947 CPP_concept integral =
948 std::is_integral<T>::value;
949
952 template<typename T>
953 CPP_concept signed_integral =
954 integral<T> &&
955 std::is_signed<T>::value;
956
959 template<typename T>
960 CPP_concept unsigned_integral =
961 integral<T> &&
962 !signed_integral<T>;
963
966 template<typename T, typename U>
967 CPP_requires(assignable_from_,
968 requires(T t, U && u) //
969 (
970 t = (U &&) u,
971 requires_<same_as<T, decltype(t = (U &&) u)>>
972 ));
975 template<typename T, typename U>
976 CPP_concept assignable_from =
977 std::is_lvalue_reference<T>::value &&
978 common_reference_with<detail::as_cref_t<T>, detail::as_cref_t<U>> &&
979 CPP_requires_ref(defs::assignable_from_, T, U);
980
983 template<typename T>
984 CPP_requires(swappable_,
985 requires(T & t, T & u) //
986 (
987 concepts::swap(t, u)
988 ));
991 template<typename T>
992 CPP_concept swappable =
993 CPP_requires_ref(defs::swappable_, T);
994
997 template<typename T, typename U>
998 CPP_requires(swappable_with_,
999 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 ));
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 } // inline namespace defs
1014
1015 namespace detail
1016 {
1019 template<typename T>
1020 CPP_concept boolean_testable_impl_ = convertible_to<T, bool>;
1021
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
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
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 ));
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
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 ));
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 } // namespace detail
1082
1083 inline namespace defs
1084 {
1086 // Comparison concepts
1088
1091 template<typename T>
1092 CPP_concept equality_comparable =
1093 detail::weakly_equality_comparable_with_<T, T>;
1094
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 );
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
1114 template<typename T>
1115 CPP_concept totally_ordered =
1116 equality_comparable<T> &&
1117 detail::partially_ordered_with_<T, T>;
1118
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
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
1139 // Object concepts
1141
1144 template<typename T>
1145 CPP_concept destructible =
1146 std::is_nothrow_destructible<T>::value;
1147
1150 template<typename T, typename... Args>
1151 CPP_concept constructible_from =
1152 destructible<T> &&
1153 META_IS_CONSTRUCTIBLE(T, Args...);
1154
1157 template<typename T>
1158 CPP_concept default_constructible =
1159 constructible_from<T>;
1160
1163 template<typename T>
1164 CPP_concept move_constructible =
1165 constructible_from<T, T> &&
1166 convertible_to<T, T>;
1167
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>);
1180 template<typename T>
1181 CPP_concept copy_constructible =
1182 move_constructible<T> &&
1183 CPP_concept_ref(concepts::copy_constructible_, T);
1184
1187 CPP_template(typename T)(
1188 concept (move_assignable_)(T),
1189 assignable_from<T &, T>
1190 );
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
1202 CPP_template(typename T)(
1203 concept (copy_assignable_)(T),
1204 assignable_from<T &, T const &>
1205 );
1208 template<typename T>
1209 CPP_concept copyable =
1210 copy_constructible<T> &&
1211 movable<T> &&
1212 CPP_concept_ref(concepts::copy_assignable_, T);
1213
1216 template<typename T>
1217 CPP_concept semiregular =
1218 copyable<T> &&
1219 default_constructible<T>;
1220 // Axiom: copies are independent. See Fundamentals of Generic
1221 // Programming http://www.stepanovpapers.com/DeSt98.pdf
1222
1225 template<typename T>
1226 CPP_concept regular =
1227 semiregular<T> &&
1228 equality_comparable<T>;
1229
1230 } // inline namespace defs
1231} // namespace concepts
1232
1233#endif // RANGES_V3_UTILITY_CONCEPTS_HPP
typename Fn::template invoke< Args... > invoke
Evaluate the invocable Fn with the arguments Args.
Definition meta.hpp:541
Definition concepts.hpp:731
Definition concepts.hpp:745