proxygen
concept_def.h
Go to the documentation of this file.
1 /*
2  * Copyright 2018-present Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #pragma once
17 
18 #include <type_traits>
19 
20 #ifndef __has_builtin
21 #define __has_builtin(x) 0
22 #endif
23 
24 // disable buggy compatibility warning about "requires" and "concept" being
25 // C++20 keywords.
26 #if defined(__clang__) && not defined(__APPLE__)
27 #define PUSHMI_PP_IGNORE_CXX2A_COMPAT_BEGIN \
28  _Pragma("GCC diagnostic push") \
29  _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"") \
30  _Pragma("GCC diagnostic ignored \"-Wpragmas\"") \
31  _Pragma("GCC diagnostic ignored \"-Wc++2a-compat\"") \
32  _Pragma("GCC diagnostic ignored \"-Wfloat-equal\"") \
33 
34 #define PUSHMI_PP_IGNORE_CXX2A_COMPAT_END \
35  _Pragma("GCC diagnostic pop")
36 #elif defined(__clang__) && defined(__APPLE__)
37 #define PUSHMI_PP_IGNORE_CXX2A_COMPAT_BEGIN \
38  _Pragma("GCC diagnostic push") \
39  _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"") \
40  _Pragma("GCC diagnostic ignored \"-Wpragmas\"") \
41  _Pragma("GCC diagnostic ignored \"-Wfloat-equal\"") \
42 
43 #define PUSHMI_PP_IGNORE_CXX2A_COMPAT_END \
44  _Pragma("GCC diagnostic pop")
45 #else
46 
47 #define PUSHMI_PP_IGNORE_CXX2A_COMPAT_BEGIN
48 #define PUSHMI_PP_IGNORE_CXX2A_COMPAT_END
49 // #pragma GCC diagnostic push
50 // #pragma GCC diagnostic ignored "-Wunknown-pragmas"
51 // #pragma GCC diagnostic ignored "-Wpragmas"
52 // #pragma GCC diagnostic ignored "-Wc++2a-compat"
53 #endif
54 
56 
57 #if __cpp_inline_variables >= 201606
58 #define PUSHMI_INLINE_VAR inline
59 #else
60 #define PUSHMI_INLINE_VAR
61 #endif
62 
63 #ifdef __clang__
64 #define PUSHMI_PP_IS_SAME(...) __is_same(__VA_ARGS__)
65 #elif defined(__GNUC__) && __GNUC__ >= 6 && !defined(__NVCC__)
66 #define PUSHMI_PP_IS_SAME(...) __is_same_as(__VA_ARGS__)
67 #else
68 #define PUSHMI_PP_IS_SAME(...) std::is_same<__VA_ARGS__>::value
69 #endif
70 
71 #ifdef __clang__
72 #define PUSHMI_PP_IS_CONSTRUCTIBLE(...) __is_constructible(__VA_ARGS__)
73 #elif defined(__GNUC__) && __GNUC__ >= 8
74 #define PUSHMI_PP_IS_CONSTRUCTIBLE(...) __is_constructible(__VA_ARGS__)
75 #else
76 #define PUSHMI_PP_IS_CONSTRUCTIBLE(...) std::is_constructible<__VA_ARGS__>::value
77 #endif
78 
79 #if __COUNTER__ != __COUNTER__
80 #define PUSHMI_COUNTER __COUNTER__
81 #else
82 #define PUSHMI_COUNTER __LINE__
83 #endif
84 
85 #define PUSHMI_PP_CHECK(...) PUSHMI_PP_CHECK_N(__VA_ARGS__, 0,)
86 #define PUSHMI_PP_CHECK_N(x, n, ...) n
87 #define PUSHMI_PP_PROBE(x) x, 1,
88 
89 // PUSHMI_CXX_VA_OPT
90 #ifndef PUSHMI_CXX_VA_OPT
91 #if __cplusplus > 201703L
92 #define PUSHMI_CXX_VA_OPT_(...) PUSHMI_PP_CHECK(__VA_OPT__(,) 1)
93 #define PUSHMI_CXX_VA_OPT PUSHMI_CXX_VA_OPT_(~)
94 #else
95 #define PUSHMI_CXX_VA_OPT 0
96 #endif
97 #endif // PUSHMI_CXX_VA_OPT
98 
99 #define PUSHMI_PP_CAT_(X, ...) X ## __VA_ARGS__
100 #define PUSHMI_PP_CAT(X, ...) PUSHMI_PP_CAT_(X, __VA_ARGS__)
101 #define PUSHMI_PP_CAT2_(X, ...) X ## __VA_ARGS__
102 #define PUSHMI_PP_CAT2(X, ...) PUSHMI_PP_CAT2_(X, __VA_ARGS__)
103 
104 #define PUSHMI_PP_EVAL(X, ...) X(__VA_ARGS__)
105 #define PUSHMI_PP_EVAL2(X, ...) X(__VA_ARGS__)
106 
107 #define PUSHMI_PP_EXPAND(...) __VA_ARGS__
108 #define PUSHMI_PP_EAT(...)
109 
110 #define PUSHMI_PP_IS_PAREN(x) PUSHMI_PP_CHECK(PUSHMI_PP_IS_PAREN_PROBE x)
111 #define PUSHMI_PP_IS_PAREN_PROBE(...) PUSHMI_PP_PROBE(~)
112 
113 #define PUSHMI_PP_COUNT(...) \
114  PUSHMI_PP_COUNT_(__VA_ARGS__, \
115  50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31, \
116  30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11, \
117  10,9,8,7,6,5,4,3,2,1,) \
118 
119 #define PUSHMI_PP_COUNT_( \
120  _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \
121  _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \
122  _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \
123  _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \
124  _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, N, ...) \
125  N \
126 
127 
128 #define PUSHMI_PP_IIF(BIT) PUSHMI_PP_CAT_(PUSHMI_PP_IIF_, BIT)
129 #define PUSHMI_PP_IIF_0(TRUE, ...) __VA_ARGS__
130 #define PUSHMI_PP_IIF_1(TRUE, ...) TRUE
131 
132 #define PUSHMI_PP_EMPTY()
133 #define PUSHMI_PP_COMMA() ,
134 #define PUSHMI_PP_COMMA_IIF(X) \
135  PUSHMI_PP_IIF(X)(PUSHMI_PP_EMPTY, PUSHMI_PP_COMMA)()
136 
137 #define PUSHMI_CONCEPT_ASSERT(...) \
138  static_assert((bool) (__VA_ARGS__), \
139  "Concept assertion failed : " #__VA_ARGS__)
140 
142 // PUSHMI_CONCEPT_DEF
143 // For defining concepts with a syntax symilar to C++20. For example:
144 //
145 // PUSHMI_CONCEPT_DEF(
146 // // The Assignable concept from the C++20
147 // template(class T, class U)
148 // concept Assignable,
149 // requires (T t, U &&u) (
150 // t = (U &&) u,
151 // ::folly::pushmi::concepts::requires_<Same<decltype(t = (U &&)
152 // u), T>>
153 // ) &&
154 // std::is_lvalue_reference_v<T>
155 // );
156 #define PUSHMI_CONCEPT_DEF(DECL, ...) \
157  PUSHMI_PP_EVAL( \
158  PUSHMI_PP_DECL_DEF, \
159  PUSHMI_PP_CAT(PUSHMI_PP_DEF_DECL_, DECL), \
160  __VA_ARGS__) \
161 
162 #define PUSHMI_PP_DECL_DEF_NAME(...) \
163  PUSHMI_PP_CAT(PUSHMI_PP_DEF_, __VA_ARGS__), \
164 
165 #define PUSHMI_PP_DECL_DEF(TPARAM, NAME, ...) \
166  PUSHMI_PP_CAT(PUSHMI_PP_DECL_DEF_, PUSHMI_PP_IS_PAREN(NAME))( \
167  TPARAM, \
168  NAME, \
169  __VA_ARGS__) \
170 
171 // The defn is of the form:
172 // template(class A, class B = void, class... Rest)
173 // (concept Name)(A, B, Rest...),
174 // // requirements...
175 #define PUSHMI_PP_DECL_DEF_1(TPARAM, NAME, ...) \
176  PUSHMI_PP_EVAL2( \
177  PUSHMI_PP_DECL_DEF_IMPL, \
178  TPARAM, \
179  PUSHMI_PP_DECL_DEF_NAME NAME, \
180  __VA_ARGS__) \
181 
182 // The defn is of the form:
183 // template(class A, class B)
184 // concept Name,
185 // // requirements...
186 // Compute the template arguments (A, B) from the template introducer.
187 #define PUSHMI_PP_DECL_DEF_0(TPARAM, NAME, ...) \
188  PUSHMI_PP_DECL_DEF_IMPL( \
189  TPARAM, \
190  PUSHMI_PP_CAT(PUSHMI_PP_DEF_, NAME), \
191  (PUSHMI_PP_CAT(PUSHMI_PP_AUX_, TPARAM)), \
192  __VA_ARGS__) \
193 
194 // Expand the template definition into a struct and template alias like:
195 // struct NameConcept {
196 // template<class A, class B>
197 // static auto Requires_(/* args (optional)*/) ->
198 // decltype(/*requirements...*/);
199 // template<class A, class B>
200 // static constexpr auto is_satisfied_by(int) ->
201 // decltype(bool(&Requires_<A,B>)) { return true; }
202 // template<class A, class B>
203 // static constexpr bool is_satisfied_by(long) { return false; }
204 // };
205 // template<class A, class B>
206 // inline constexpr bool Name = NameConcept::is_satisfied_by<A, B>(0);
207 #if __cpp_concepts
208 // No requires expression
209 #define PUSHMI_PP_DEF_IMPL_0(...) \
210  __VA_ARGS__ \
211 
212 // Requires expression
213 #define PUSHMI_PP_DEF_IMPL_1(...) \
214  PUSHMI_PP_CAT(PUSHMI_PP_DEF_IMPL_1_, __VA_ARGS__) \
215 
216 #define PUSHMI_PP_DEF_IMPL_1_requires \
217  requires PUSHMI_PP_DEF_IMPL_1_REQUIRES \
218 
219 #define PUSHMI_PP_DEF_IMPL_1_REQUIRES(...) \
220  (__VA_ARGS__) PUSHMI_PP_DEF_IMPL_1_REQUIRES_BODY \
221 
222 #define PUSHMI_PP_DEF_IMPL_1_REQUIRES_BODY(...) \
223  { __VA_ARGS__; } \
224 
225 #define PUSHMI_PP_DECL_DEF_IMPL(TPARAM, NAME, ARGS, ...) \
226  inline namespace _eager_ { \
227  PUSHMI_PP_CAT(PUSHMI_PP_DEF_, TPARAM) \
228  concept bool NAME = PUSHMI_PP_DEF_IMPL(__VA_ARGS__)(__VA_ARGS__); \
229  } \
230  namespace lazy = _eager_; \
231 
232 #else
233 // No requires expression:
234 #define PUSHMI_PP_DEF_IMPL_0(...) \
235  () -> std::enable_if_t<bool(__VA_ARGS__), int> \
236 
237 // Requires expression:
238 #define PUSHMI_PP_DEF_IMPL_1(...) \
239  PUSHMI_PP_CAT(PUSHMI_PP_DEF_IMPL_1_, __VA_ARGS__) ), int> \
240 
241 #define PUSHMI_PP_DEF_IMPL_1_requires \
242  PUSHMI_PP_DEF_IMPL_1_REQUIRES \
243 
244 #define PUSHMI_PP_DEF_IMPL_1_REQUIRES(...) \
245  (__VA_ARGS__) -> std::enable_if_t<bool( \
246  ::folly::pushmi::concepts::detail::requires_ \
247  PUSHMI_PP_DEF_REQUIRES_BODY \
248 
249 #define PUSHMI_PP_DEF_REQUIRES_BODY(...) \
250  <decltype(__VA_ARGS__, void())>() \
251 
252 #define PUSHMI_PP_DECL_DEF_IMPL(TPARAM, NAME, ARGS, ...) \
253  struct PUSHMI_PP_CAT(NAME, Concept) { \
254  using Concept = PUSHMI_PP_CAT(NAME, Concept); \
255  PUSHMI_PP_IGNORE_CXX2A_COMPAT_BEGIN \
256  PUSHMI_PP_CAT(PUSHMI_PP_DEF_, TPARAM) \
257  static auto Requires_ PUSHMI_PP_DEF_IMPL(__VA_ARGS__)(__VA_ARGS__) { \
258  return 0; \
259  } \
260  PUSHMI_PP_IGNORE_CXX2A_COMPAT_END \
261  PUSHMI_PP_CAT(PUSHMI_PP_DEF_, TPARAM) \
262  struct Eval { \
263  template <class C_ = Concept> \
264  static constexpr decltype(::folly::pushmi::concepts::detail::gcc_bugs( \
265  &C_::template Requires_<PUSHMI_PP_EXPAND ARGS>)) \
266  impl(int) noexcept { \
267  return true; \
268  } \
269  static constexpr bool impl(long) noexcept { \
270  return false; \
271  } \
272  explicit constexpr operator bool() const noexcept { \
273  return Eval::impl(0); \
274  } \
275  template < \
276  class PMThis = Concept, \
277  bool PMB, \
278  class = std::enable_if_t<PMB == (bool)PMThis{}>> \
279  constexpr operator std::integral_constant<bool, PMB>() const noexcept { \
280  return {}; \
281  } \
282  constexpr auto operator!() const noexcept { \
283  return ::folly::pushmi::concepts::detail::Not<Eval>{}; \
284  } \
285  template <class That> \
286  constexpr auto operator&&(That) const noexcept { \
287  return ::folly::pushmi::concepts::detail::And<Eval, That>{}; \
288  } \
289  template <class That> \
290  constexpr auto operator||(That) const noexcept { \
291  return ::folly::pushmi::concepts::detail::Or<Eval, That>{}; \
292  } \
293  }; \
294  }; \
295  namespace lazy { \
296  PUSHMI_PP_CAT(PUSHMI_PP_DEF_, TPARAM) \
297  PUSHMI_INLINE_VAR constexpr auto NAME = \
298  PUSHMI_PP_CAT(NAME, Concept)::Eval<PUSHMI_PP_EXPAND ARGS>{}; \
299  } \
300  PUSHMI_PP_CAT(PUSHMI_PP_DEF_, TPARAM) \
301  PUSHMI_INLINE_VAR constexpr bool NAME = \
302  (bool)PUSHMI_PP_CAT(NAME, Concept)::Eval<PUSHMI_PP_EXPAND ARGS> {} \
303 
304 #endif
305 
306 #define PUSHMI_PP_REQUIRES_PROBE_requires \
307  PUSHMI_PP_PROBE(~) \
308 
309 #define PUSHMI_PP_DEF_IMPL(REQUIRES, ...) \
310  PUSHMI_PP_CAT( \
311  PUSHMI_PP_DEF_IMPL_, \
312  PUSHMI_PP_CHECK(PUSHMI_PP_CAT(PUSHMI_PP_REQUIRES_PROBE_, REQUIRES))) \
313 
314 #define PUSHMI_PP_DEF_DECL_template(...) \
315  template(__VA_ARGS__), \
316 
317 #define PUSHMI_PP_DEF_template(...) \
318  template<__VA_ARGS__> \
319 
320 #define PUSHMI_PP_DEF_concept
321 #define PUSHMI_PP_DEF_class
322 #define PUSHMI_PP_DEF_typename
323 #define PUSHMI_PP_DEF_int
324 #define PUSHMI_PP_DEF_bool
325 #define PUSHMI_PP_DEF_size_t
326 #define PUSHMI_PP_DEF_unsigned
327 #define PUSHMI_PP_AUX_template(...) \
328  PUSHMI_PP_CAT2( \
329  PUSHMI_PP_TPARAM_, \
330  PUSHMI_PP_COUNT(__VA_ARGS__))(__VA_ARGS__) \
331 
332 #define PUSHMI_PP_TPARAM_1(_1) \
333  PUSHMI_PP_CAT2(PUSHMI_PP_DEF_, _1)
334 #define PUSHMI_PP_TPARAM_2(_1, ...) \
335  PUSHMI_PP_CAT2(PUSHMI_PP_DEF_, _1), PUSHMI_PP_TPARAM_1(__VA_ARGS__)
336 #define PUSHMI_PP_TPARAM_3(_1, ...) \
337  PUSHMI_PP_CAT2(PUSHMI_PP_DEF_, _1), PUSHMI_PP_TPARAM_2(__VA_ARGS__)
338 #define PUSHMI_PP_TPARAM_4(_1, ...) \
339  PUSHMI_PP_CAT2(PUSHMI_PP_DEF_, _1), PUSHMI_PP_TPARAM_3(__VA_ARGS__)
340 #define PUSHMI_PP_TPARAM_5(_1, ...) \
341  PUSHMI_PP_CAT2(PUSHMI_PP_DEF_, _1), PUSHMI_PP_TPARAM_4(__VA_ARGS__)
342 
344 // PUSHMI_TEMPLATE
345 // Usage:
346 // PUSHMI_TEMPLATE (class A, class B)
347 // (requires Concept1<A> && Concept2<B>)
348 // void foo(A a, B b)
349 // {}
350 // or
351 // PUSHMI_TEMPLATE (class A, class B)
352 // (requires requires (expr1, expr2, expr3) && Concept1<A> && Concept2<B>)
353 // void foo(A a, B b)
354 // {}
355 #if __cpp_concepts
356 #define PUSHMI_TEMPLATE(...) \
357  template<__VA_ARGS__> PUSHMI_TEMPLATE_AUX_ \
358 
359 #define PUSHMI_TEMPLATE_AUX_(...) \
360  PUSHMI_TEMPLATE_AUX_4(PUSHMI_PP_CAT(PUSHMI_TEMPLATE_AUX_3_, __VA_ARGS__)) \
361 
362 #define PUSHMI_TEMPLATE_AUX_3_requires
363 #define PUSHMI_TEMPLATE_AUX_4(...) \
364  PUSHMI_TEMPLATE_AUX_5(__VA_ARGS__)(__VA_ARGS__) \
365 
366 #define PUSHMI_TEMPLATE_AUX_5(REQUIRES, ...) \
367  PUSHMI_PP_CAT( \
368  PUSHMI_TEMPLATE_AUX_5_, \
369  PUSHMI_PP_CHECK(PUSHMI_PP_CAT(PUSHMI_PP_REQUIRES_PROBE_, REQUIRES))) \
370 
371 // No requires expression:
372 #define PUSHMI_TEMPLATE_AUX_5_0(...) \
373  requires __VA_ARGS__ \
374 
375 // Requires expression
376 #define PUSHMI_TEMPLATE_AUX_5_1(...) \
377  PUSHMI_PP_CAT(PUSHMI_TEMPLATE_AUX_6_, __VA_ARGS__) \
378 
379 #define PUSHMI_TEMPLATE_AUX_6_requires(...)\
380  requires requires { __VA_ARGS__; }
381 #else
382 #define PUSHMI_TEMPLATE(...) \
383  template<__VA_ARGS__ PUSHMI_TEMPLATE_AUX_
384 #define PUSHMI_TEMPLATE_AUX_(...) , \
385  int (*PUSHMI_PP_CAT(_pushmi_concept_unique_, __LINE__))[ \
386  PUSHMI_COUNTER] = nullptr, \
387  std::enable_if_t<PUSHMI_PP_CAT(_pushmi_concept_unique_, __LINE__) || \
388  bool(PUSHMI_TEMPLATE_AUX_4(PUSHMI_PP_CAT( \
389  PUSHMI_TEMPLATE_AUX_3_, __VA_ARGS__))), int> = 0> \
390 
391 #define PUSHMI_TEMPLATE_AUX_3_requires
392 #define PUSHMI_TEMPLATE_AUX_4(...) \
393  PUSHMI_TEMPLATE_AUX_5(__VA_ARGS__)(__VA_ARGS__) \
394 
395 #define PUSHMI_TEMPLATE_AUX_5(REQUIRES, ...) \
396  PUSHMI_PP_CAT( \
397  PUSHMI_TEMPLATE_AUX_5_, \
398  PUSHMI_PP_CHECK(PUSHMI_PP_CAT(PUSHMI_PP_REQUIRES_PROBE_, REQUIRES))) \
399 
400 // No requires expression:
401 #define PUSHMI_TEMPLATE_AUX_5_0(...) \
402  __VA_ARGS__ \
403 
404 #define PUSHMI_TEMPLATE_AUX_5_1(...) \
405  PUSHMI_PP_CAT(PUSHMI_TEMPLATE_AUX_6_, __VA_ARGS__) \
406 
407 #define PUSHMI_TEMPLATE_AUX_6_requires(...) \
408  ::folly::pushmi::concepts::detail::requires_<decltype(__VA_ARGS__)>() \
409 
410 #endif
411 
412 
413 #if __cpp_concepts
414 #define PUSHMI_BROKEN_SUBSUMPTION(...)
415 #define PUSHMI_TYPE_CONSTRAINT(...) __VA_ARGS__
416 #define PUSHMI_EXP(...) __VA_ARGS__
417 #define PUSHMI_AND &&
418 #else
419 #define PUSHMI_BROKEN_SUBSUMPTION(...) __VA_ARGS__
420 #define PUSHMI_TYPE_CONSTRAINT(...) class
421 // bool() is used to prevent 'error: pasting "PUSHMI_PP_REQUIRES_PROBE_" and
422 // "::" does not give a valid preprocessing token'
423 #define PUSHMI_EXP(...) bool(::folly::pushmi::expAnd(__VA_ARGS__))
424 #define PUSHMI_AND ,
425 #endif
426 
427 
428 #if __cpp_concepts
429 #define PUSHMI_PP_CONSTRAINED_USING(REQUIRES, NAME, ...) \
430  requires REQUIRES \
431  using NAME __VA_ARGS__ \
432 
433 #else
434 #define PUSHMI_PP_CONSTRAINED_USING(REQUIRES, NAME, ...) \
435  using NAME std::enable_if_t<bool(REQUIRES), __VA_ARGS__> \
436 
437 #endif
438 
439 namespace folly {
440 namespace pushmi {
441 
442 template <bool B>
443 using bool_ = std::integral_constant<bool, B>;
444 
445 namespace concepts {
446 namespace detail {
447 bool gcc_bugs(...);
448 
449 template <class>
450 inline constexpr bool requires_() {
451  return true;
452 }
453 
454 template <class T, class U>
455 struct And;
456 template <class T, class U>
457 struct Or;
458 
459 template <class T>
460 struct Not {
461  explicit constexpr operator bool() const noexcept {
462  return !(bool)T{};
463  }
464  PUSHMI_TEMPLATE(class This = Not, bool B)
465  (requires B == (bool)This{}) constexpr
466  operator std::integral_constant<bool, B>() const noexcept {
467  return {};
468  }
469  constexpr auto operator!() const noexcept {
470  return T{};
471  }
472  template <class That>
473  constexpr auto operator&&(That) const noexcept {
474  return And<Not, That>{};
475  }
476  template <class That>
477  constexpr auto operator||(That) const noexcept {
478  return Or<Not, That>{};
479  }
480 };
481 
482 template <class T, class U>
483 struct And {
484  explicit constexpr operator bool() const noexcept {
485  return (bool)std::conditional_t<(bool)T{}, U, std::false_type>{};
486  }
487  PUSHMI_TEMPLATE(class This = And, bool B)
488  (requires B == (bool)This{}) constexpr
489  operator std::integral_constant<bool, B>() const noexcept {
490  return {};
491  }
492  constexpr auto operator!() const noexcept {
493  return Not<And>{};
494  }
495  template <class That>
496  constexpr auto operator&&(That) const noexcept {
497  return And<And, That>{};
498  }
499  template <class That>
500  constexpr auto operator||(That) const noexcept {
501  return Or<And, That>{};
502  }
503 };
504 
505 template <class T, class U>
506 struct Or {
507  explicit constexpr operator bool() const noexcept {
508  return (bool)std::conditional_t<(bool)T{}, std::true_type, U>{};
509  }
510  PUSHMI_TEMPLATE(class This = Or, bool B)
511  (requires B == (bool)This{}) constexpr
512  operator std::integral_constant<bool, B>() const noexcept {
513  return {};
514  }
515  constexpr auto operator!() const noexcept {
516  return Not<Or>{};
517  }
518  template <class That>
519  constexpr auto operator&&(That) const noexcept {
520  return And<Or, That>{};
521  }
522  template <class That>
523  constexpr auto operator||(That) const noexcept {
524  return Or<Or, That>{};
525  }
526 };
527 } // namespace detail
528 } // namespace concepts
529 
530 namespace isolated {
531 
532 template <class T0>
533 constexpr auto expAnd(T0&& t0) {
534  return (T0 &&) t0;
535 }
536 template <class T0, class... TN>
537 constexpr auto expAnd(T0&&, TN&&... tn) {
538  return concepts::detail::And<T0, decltype(isolated::expAnd((TN &&) tn...))>{};
539 }
540 
541 } // namespace isolated
542 
543 template <class... TN>
544 constexpr auto expAnd(TN&&... tn) {
545  return isolated::expAnd((TN &&) tn...);
546 }
547 
548 template <class T>
549 constexpr bool implicitly_convertible_to(T) {
550  return true;
551 }
552 #ifdef __clang__
553 template <bool B>
554 std::enable_if_t<B> requires_() {}
555 #else
556 template <bool B>
557 PUSHMI_INLINE_VAR constexpr std::enable_if_t<B, int> requires_ = 0;
558 #endif
559 } // namespace pushmi
560 } // namespace folly
561 
constexpr auto expAnd(T0 &&t0)
Definition: concept_def.h:530
constexpr bool implicitly_convertible_to(T)
Definition: concept_def.h:546
constexpr auto operator!() const noexcept
Definition: concept_def.h:468
folly::std T
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
requires E e noexcept(noexcept(s.error(std::move(e))))
constexpr auto expAnd(TN &&...tn)
Definition: concept_def.h:541
bool_constant< true > true_type
Definition: gtest-port.h:2210
#define PUSHMI_PP_IGNORE_CXX2A_COMPAT_BEGIN
Definition: concept_def.h:47
constexpr auto operator&&(That) const noexcept
Definition: concept_def.h:472
#define PUSHMI_INLINE_VAR
Definition: concept_def.h:60
std::integral_constant< bool, B > bool_
Definition: concept_def.h:443
requires requires(detail::apply_impl(std::declval< F >(), std::declval< Tuple >(), detail::tupidxs< Tuple >{}))) const expr decltype(auto) apply(F &&f
PUSHMI_TEMPLATE(class E=std::exception_ptr, class Wrapped)(requires Sender< detail
Definition: executor.h:102
const
Definition: upload.py:398
#define PUSHMI_PP_IGNORE_CXX2A_COMPAT_END
Definition: concept_def.h:48
bool_constant< false > false_type
Definition: gtest-port.h:2209
constexpr auto operator||(That) const noexcept
Definition: concept_def.h:476