AimRT/install_x64/include/unifex/detail/concept_macros.hpp
2025-01-12 19:51:34 +08:00

306 lines
11 KiB
C++

/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* Licensed under the Apache License Version 2.0 with LLVM Exceptions
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* https://llvm.org/LICENSE.txt
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <type_traits>
#include <unifex/config.hpp>
#include <unifex/type_traits.hpp>
#if defined(_MSC_VER) && !defined(__clang__)
#define UNIFEX_WORKAROUND_MSVC_779763 // FATAL_UNREACHABLE calling constexpr function via template parameter
#define UNIFEX_WORKAROUND_MSVC_780775 // Incorrect substitution in function template return type
#endif
#define UNIFEX_PP_CAT_(X, ...) X ## __VA_ARGS__
#define UNIFEX_PP_CAT(X, ...) UNIFEX_PP_CAT_(X, __VA_ARGS__)
#define UNIFEX_PP_CAT2_(X, ...) X ## __VA_ARGS__
#define UNIFEX_PP_CAT2(X, ...) UNIFEX_PP_CAT2_(X, __VA_ARGS__)
#define UNIFEX_PP_CAT3_(X, ...) X ## __VA_ARGS__
#define UNIFEX_PP_CAT3(X, ...) UNIFEX_PP_CAT3_(X, __VA_ARGS__)
#define UNIFEX_PP_CAT4_(X, ...) X ## __VA_ARGS__
#define UNIFEX_PP_CAT4(X, ...) UNIFEX_PP_CAT4_(X, __VA_ARGS__)
#define UNIFEX_PP_EVAL_(X, ARGS) X ARGS
#define UNIFEX_PP_EVAL(X, ...) UNIFEX_PP_EVAL_(X, (__VA_ARGS__))
#define UNIFEX_PP_EVAL2_(X, ARGS) X ARGS
#define UNIFEX_PP_EVAL2(X, ...) UNIFEX_PP_EVAL2_(X, (__VA_ARGS__))
#define UNIFEX_PP_EXPAND(...) __VA_ARGS__
#define UNIFEX_PP_EAT(...)
#define UNIFEX_PP_CHECK(...) UNIFEX_PP_EXPAND(UNIFEX_PP_CHECK_N(__VA_ARGS__, 0,))
#define UNIFEX_PP_CHECK_N(x, n, ...) n
#define UNIFEX_PP_PROBE(x) x, 1,
#define UNIFEX_PP_PROBE_N(x, n) x, n,
#define UNIFEX_PP_IS_PAREN(x) UNIFEX_PP_CHECK(UNIFEX_PP_IS_PAREN_PROBE x)
#define UNIFEX_PP_IS_PAREN_PROBE(...) UNIFEX_PP_PROBE(~)
// The final UNIFEX_PP_EXPAND here is to avoid
// https://stackoverflow.com/questions/5134523/msvc-doesnt-expand-va-args-correctly
#define UNIFEX_PP_COUNT(...) \
UNIFEX_PP_EXPAND(UNIFEX_PP_COUNT_(__VA_ARGS__, \
50, 49, 48, 47, 46, 45, 44, 43, 42, 41, \
40, 39, 38, 37, 36, 35, 34, 33, 32, 31, \
30, 29, 28, 27, 26, 25, 24, 23, 22, 21, \
20, 19, 18, 17, 16, 15, 14, 13, 12, 11, \
10, 9, 8, 7, 6, 5, 4, 3, 2, 1,)) \
/**/
#define UNIFEX_PP_COUNT_( \
_01, _02, _03, _04, _05, _06, _07, _08, _09, _10, \
_11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \
_21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \
_31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \
_41, _42, _43, _44, _45, _46, _47, _48, _49, _50, N, ...) \
N \
/**/
#define UNIFEX_PP_IIF(BIT) UNIFEX_PP_CAT_(UNIFEX_PP_IIF_, BIT)
#define UNIFEX_PP_IIF_0(TRUE, ...) __VA_ARGS__
#define UNIFEX_PP_IIF_1(TRUE, ...) TRUE
#define UNIFEX_PP_LPAREN (
#define UNIFEX_PP_NOT(BIT) UNIFEX_PP_CAT_(UNIFEX_PP_NOT_, BIT)
#define UNIFEX_PP_NOT_0 1
#define UNIFEX_PP_NOT_1 0
#define UNIFEX_PP_EMPTY()
#define UNIFEX_PP_COMMA() ,
#define UNIFEX_PP_LBRACE() {
#define UNIFEX_PP_RBRACE() }
#define UNIFEX_PP_COMMA_IIF(X) \
UNIFEX_PP_IIF(X)(UNIFEX_PP_EMPTY, UNIFEX_PP_COMMA)() \
/**/
#define UNIFEX_PP_FOR_EACH(M, ...) \
UNIFEX_PP_FOR_EACH_N(UNIFEX_PP_COUNT(__VA_ARGS__), M, __VA_ARGS__)
#define UNIFEX_PP_FOR_EACH_N(N, M, ...) \
UNIFEX_PP_CAT2(UNIFEX_PP_FOR_EACH_, N)(M, __VA_ARGS__)
#define UNIFEX_PP_FOR_EACH_1(M, _1) \
M(_1)
#define UNIFEX_PP_FOR_EACH_2(M, _1, _2) \
M(_1) M(_2)
#define UNIFEX_PP_FOR_EACH_3(M, _1, _2, _3) \
M(_1) M(_2) M(_3)
#define UNIFEX_PP_FOR_EACH_4(M, _1, _2, _3, _4) \
M(_1) M(_2) M(_3) M(_4)
#define UNIFEX_PP_FOR_EACH_5(M, _1, _2, _3, _4, _5) \
M(_1) M(_2) M(_3) M(_4) M(_5)
#define UNIFEX_PP_FOR_EACH_6(M, _1, _2, _3, _4, _5, _6) \
M(_1) M(_2) M(_3) M(_4) M(_5) M(_6)
#define UNIFEX_PP_FOR_EACH_7(M, _1, _2, _3, _4, _5, _6, _7) \
M(_1) M(_2) M(_3) M(_4) M(_5) M(_6) M(_7)
#define UNIFEX_PP_FOR_EACH_8(M, _1, _2, _3, _4, _5, _6, _7, _8) \
M(_1) M(_2) M(_3) M(_4) M(_5) M(_6) M(_7) M(_8)
#define UNIFEX_PP_PROBE_EMPTY_PROBE_UNIFEX_PP_PROBE_EMPTY \
UNIFEX_PP_PROBE(~) \
#define UNIFEX_PP_PROBE_EMPTY()
#define UNIFEX_PP_IS_NOT_EMPTY(...) \
UNIFEX_PP_EVAL( \
UNIFEX_PP_CHECK, \
UNIFEX_PP_CAT( \
UNIFEX_PP_PROBE_EMPTY_PROBE_, \
UNIFEX_PP_PROBE_EMPTY __VA_ARGS__ ())) \
/**/
#define UNIFEX_PP_TAIL(_, ...) __VA_ARGS__
#define UNIFEX_CONCEPT_FRAGMENT_REQS_M0(REQ) \
UNIFEX_CONCEPT_FRAGMENT_REQS_SELECT_(REQ)(REQ)
#define UNIFEX_CONCEPT_FRAGMENT_REQS_M1(REQ) UNIFEX_PP_EXPAND REQ
#define UNIFEX_CONCEPT_FRAGMENT_REQS_(...) \
{ UNIFEX_PP_FOR_EACH(UNIFEX_CONCEPT_FRAGMENT_REQS_M, __VA_ARGS__) }
#define UNIFEX_CONCEPT_FRAGMENT_REQS_SELECT_(REQ) \
UNIFEX_PP_CAT3(UNIFEX_CONCEPT_FRAGMENT_REQS_SELECT_, \
UNIFEX_PP_EVAL(UNIFEX_PP_CHECK, UNIFEX_PP_CAT3( \
UNIFEX_CONCEPT_FRAGMENT_REQS_SELECT_PROBE_, \
REQ))) \
/**/
#define UNIFEX_CONCEPT_FRAGMENT_REQS_SELECT_PROBE_requires UNIFEX_PP_PROBE_N(~, 1)
#define UNIFEX_CONCEPT_FRAGMENT_REQS_SELECT_PROBE_noexcept UNIFEX_PP_PROBE_N(~, 2)
#define UNIFEX_CONCEPT_FRAGMENT_REQS_SELECT_PROBE_typename UNIFEX_PP_PROBE_N(~, 3)
#define UNIFEX_CONCEPT_FRAGMENT_REQS_SELECT_0 UNIFEX_PP_EXPAND
#define UNIFEX_CONCEPT_FRAGMENT_REQS_SELECT_1 UNIFEX_CONCEPT_FRAGMENT_REQS_REQUIRES_OR_NOEXCEPT
#define UNIFEX_CONCEPT_FRAGMENT_REQS_SELECT_2 UNIFEX_CONCEPT_FRAGMENT_REQS_REQUIRES_OR_NOEXCEPT
#define UNIFEX_CONCEPT_FRAGMENT_REQS_SELECT_3 UNIFEX_CONCEPT_FRAGMENT_REQS_REQUIRES_OR_NOEXCEPT
#define UNIFEX_CONCEPT_FRAGMENT_REQS_REQUIRES_OR_NOEXCEPT(REQ) \
UNIFEX_PP_CAT4( \
UNIFEX_CONCEPT_FRAGMENT_REQS_REQUIRES_, \
REQ)
#define UNIFEX_PP_EAT_TYPENAME_PROBE_typename UNIFEX_PP_PROBE(~)
#define UNIFEX_PP_EAT_TYPENAME_SELECT_(X,...) \
UNIFEX_PP_CAT3(UNIFEX_PP_EAT_TYPENAME_SELECT_, \
UNIFEX_PP_EVAL(UNIFEX_PP_CHECK, UNIFEX_PP_CAT3( \
UNIFEX_PP_EAT_TYPENAME_PROBE_, \
X)))
#define UNIFEX_PP_EAT_TYPENAME_(...) \
UNIFEX_PP_EVAL2(UNIFEX_PP_EAT_TYPENAME_SELECT_, __VA_ARGS__,)(__VA_ARGS__)
#define UNIFEX_PP_EAT_TYPENAME_SELECT_0(...) __VA_ARGS__
#define UNIFEX_PP_EAT_TYPENAME_SELECT_1(...) \
UNIFEX_PP_CAT3(UNIFEX_PP_EAT_TYPENAME_, __VA_ARGS__)
#define UNIFEX_PP_EAT_TYPENAME_typename
#if UNIFEX_CXX_CONCEPTS || defined(UNIFEX_DOXYGEN_INVOKED)
#define UNIFEX_CONCEPT concept
#define UNIFEX_CONCEPT_FRAGMENT(NAME, ...) \
concept NAME = UNIFEX_PP_CAT(UNIFEX_CONCEPT_FRAGMENT_REQS_, __VA_ARGS__)
#define UNIFEX_CONCEPT_FRAGMENT_REQS_requires(...) \
requires(__VA_ARGS__) UNIFEX_CONCEPT_FRAGMENT_REQS_
#define UNIFEX_CONCEPT_FRAGMENT_REQS_M(REQ) \
UNIFEX_PP_CAT2(UNIFEX_CONCEPT_FRAGMENT_REQS_M, UNIFEX_PP_IS_PAREN(REQ))(REQ);
#define UNIFEX_CONCEPT_FRAGMENT_REQS_REQUIRES_requires(...) \
requires __VA_ARGS__
#define UNIFEX_CONCEPT_FRAGMENT_REQS_REQUIRES_typename(...) \
typename UNIFEX_PP_EAT_TYPENAME_(__VA_ARGS__)
#define UNIFEX_CONCEPT_FRAGMENT_REQS_REQUIRES_noexcept(...) \
{ __VA_ARGS__ } noexcept
#define UNIFEX_FRAGMENT(NAME, ...) \
NAME<__VA_ARGS__>
#else
#define UNIFEX_CONCEPT inline constexpr bool
#define UNIFEX_CONCEPT_FRAGMENT(NAME, ...) \
auto NAME ## UNIFEX_CONCEPT_FRAGMENT_impl_ \
UNIFEX_CONCEPT_FRAGMENT_REQS_ ## __VA_ARGS__> {} \
template <typename... As> \
char NAME ## UNIFEX_CONCEPT_FRAGMENT_( \
::unifex::_concept::tag<As...> *, \
decltype(&NAME ## UNIFEX_CONCEPT_FRAGMENT_impl_<As...>)); \
char (&NAME ## UNIFEX_CONCEPT_FRAGMENT_(...))[2] \
/**/
#if defined(_MSC_VER) && !defined(__clang__)
#define UNIFEX_CONCEPT_FRAGMENT_TRUE(...) \
::unifex::_concept::true_<decltype( \
UNIFEX_PP_FOR_EACH(UNIFEX_CONCEPT_FRAGMENT_REQS_M, __VA_ARGS__) \
void())>()
#else
#define UNIFEX_CONCEPT_FRAGMENT_TRUE(...) \
!(decltype(UNIFEX_PP_FOR_EACH(UNIFEX_CONCEPT_FRAGMENT_REQS_M, __VA_ARGS__) \
void(), \
false){})
#endif
#define UNIFEX_CONCEPT_FRAGMENT_REQS_requires(...) \
(__VA_ARGS__) -> std::enable_if_t<UNIFEX_CONCEPT_FRAGMENT_REQS_2_
#define UNIFEX_CONCEPT_FRAGMENT_REQS_2_(...) \
UNIFEX_CONCEPT_FRAGMENT_TRUE(__VA_ARGS__)
#define UNIFEX_CONCEPT_FRAGMENT_REQS_M(REQ) \
UNIFEX_PP_CAT2(UNIFEX_CONCEPT_FRAGMENT_REQS_M, UNIFEX_PP_IS_PAREN(REQ))(REQ),
#define UNIFEX_CONCEPT_FRAGMENT_REQS_REQUIRES_requires(...) \
::unifex::requires_<__VA_ARGS__>
#define UNIFEX_CONCEPT_FRAGMENT_REQS_REQUIRES_typename(...) \
static_cast<::unifex::_concept::tag<__VA_ARGS__> *>(nullptr)
#if defined(__GNUC__) && !defined(__clang__)
// GCC can't mangle noexcept expressions, so just check that the
// expression is well-formed.
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70790
#define UNIFEX_CONCEPT_FRAGMENT_REQS_REQUIRES_noexcept(...) \
__VA_ARGS__
#else
#define UNIFEX_CONCEPT_FRAGMENT_REQS_REQUIRES_noexcept(...) \
::unifex::requires_<noexcept(__VA_ARGS__)>
#endif
#define UNIFEX_FRAGMENT(NAME, ...) \
(1u==sizeof(NAME ## UNIFEX_CONCEPT_FRAGMENT_( \
static_cast<::unifex::_concept::tag<__VA_ARGS__> *>(nullptr), nullptr)))
#endif
////////////////////////////////////////////////////////////////////////////////
// UNIFEX_TEMPLATE
// Usage:
// UNIFEX_TEMPLATE(typename A, typename B)
// (requires Concept1<A> UNIFEX_AND Concept2<B>)
// void foo(A a, B b)
// {}
#if UNIFEX_CXX_CONCEPTS
#define UNIFEX_TEMPLATE(...) \
template <__VA_ARGS__> UNIFEX_PP_EXPAND \
/**/
#define UNIFEX_AND && \
/**/
#else
#define UNIFEX_TEMPLATE(...) \
template <__VA_ARGS__ UNIFEX_TEMPLATE_SFINAE_AUX_ \
/**/
#define UNIFEX_AND && UNIFEX_true_, int> = 0, std::enable_if_t< \
/**/
#endif
#define UNIFEX_TEMPLATE_SFINAE(...) \
template <__VA_ARGS__ UNIFEX_TEMPLATE_SFINAE_AUX_ \
/**/
#define UNIFEX_TEMPLATE_SFINAE_AUX_(...) , \
bool UNIFEX_true_ = true, \
std::enable_if_t< \
UNIFEX_PP_CAT(UNIFEX_TEMPLATE_SFINAE_AUX_3_, __VA_ARGS__) && UNIFEX_true_, \
int> = 0> \
/**/
#define UNIFEX_TEMPLATE_SFINAE_AUX_3_requires
#include <unifex/detail/prologue.hpp>
namespace unifex {
namespace _concept {
template <typename...>
struct tag;
template <class>
inline constexpr bool true_() {
return true;
}
} // namespace _concept
#if defined(__clang__) || defined(_MSC_VER)
template <bool B>
std::enable_if_t<B> requires_() {}
#else
template <bool B>
inline constexpr std::enable_if_t<B, int> requires_ = 0;
#endif
#if UNIFEX_CXX_CONCEPTS
template <typename Fn, typename... As>
concept //
callable = //
requires (Fn&& fn, As&&... as) {
((Fn&&) fn)((As&&) as...);
};
#else
template <typename Fn, typename... As>
UNIFEX_CONCEPT //
callable = //
sizeof(decltype(_is_callable::_try_call(static_cast<Fn(*)(As...)>(nullptr)))) ==
sizeof(_is_callable::yes_type);
#endif
} // namespace unifex
#include <unifex/detail/epilogue.hpp>