File indexing completed on 2025-01-18 10:07:42
0001
0002
0003 #ifndef QXPFUNCTIONAL_H
0004 #define QXPFUNCTIONAL_H
0005
0006 #include <QtCore/qglobal.h>
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024 #include <QtCore/q23functional.h>
0025 #include <QtCore/q20type_traits.h>
0026 #include <utility>
0027
0028 QT_BEGIN_NAMESPACE
0029
0030 namespace qxp {
0031
0032
0033
0034 template<class... S> class function_ref;
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045 namespace detail {
0046
0047 template <typename T>
0048 using if_function = std::enable_if_t<std::is_function_v<T>, bool>;
0049 template <typename T>
0050 using if_non_function = std::enable_if_t<!std::is_function_v<T>, bool>;
0051
0052 template <typename From, typename To>
0053 using copy_const_t = std::conditional_t<
0054 std::is_const_v<From>,
0055 std::add_const_t<To>,
0056 To
0057 >;
0058
0059 template <class Const>
0060 union BoundEntityType {
0061 template <typename F, if_function<F> = true>
0062 explicit constexpr BoundEntityType(F *f)
0063 : fun(reinterpret_cast<QFunctionPointer>(f)) {}
0064 template <typename T, if_non_function<T> = true>
0065 explicit constexpr BoundEntityType(T *t)
0066 : obj(static_cast<Const*>(t)) {}
0067 Const *obj;
0068 QFunctionPointer fun;
0069 };
0070
0071 template <bool noex, class Const, class R, class... ArgTypes>
0072 class function_ref_base
0073 {
0074 protected:
0075 ~function_ref_base() = default;
0076
0077 using BoundEntityType = detail::BoundEntityType<Const>;
0078
0079 template <typename... Ts>
0080 using is_invocable_using = std::conditional_t<
0081 noex,
0082 std::is_nothrow_invocable_r<R, Ts..., ArgTypes...>,
0083 std::is_invocable_r<R, Ts..., ArgTypes...>
0084 >;
0085
0086 using ThunkPtr = R(*)(BoundEntityType, ArgTypes&&...) noexcept(noex);
0087
0088 BoundEntityType m_bound_entity;
0089 ThunkPtr m_thunk_ptr;
0090
0091 public:
0092 template<
0093 class F,
0094 std::enable_if_t<std::conjunction_v<
0095 std::is_function<F>,
0096 is_invocable_using<F>
0097 >, bool> = true
0098 >
0099 Q_IMPLICIT function_ref_base(F* f) noexcept
0100 : m_bound_entity(f),
0101 m_thunk_ptr([](BoundEntityType ctx, ArgTypes&&... args) noexcept(noex) -> R {
0102 return q23::invoke_r<R>(reinterpret_cast<F*>(ctx.fun),
0103 std::forward<ArgTypes>(args)...);
0104 })
0105 {}
0106
0107 template<
0108 class F,
0109 std::enable_if_t<std::conjunction_v<
0110 std::negation<std::is_same<q20::remove_cvref_t<F>, function_ref_base>>,
0111 #ifdef Q_OS_VXWORKS
0112
0113
0114
0115
0116
0117 std::negation<
0118 std::is_same<
0119 q20::remove_cvref_t<F>,
0120 std::conditional_t<
0121 std::is_const_v<Const>,
0122 qxp::function_ref<R(ArgTypes...) const noexcept(noex)>,
0123 qxp::function_ref<R(ArgTypes...) noexcept(noex)>
0124 >
0125 >
0126 >,
0127 #endif
0128 std::negation<std::is_member_pointer<std::remove_reference_t<F>>>,
0129 is_invocable_using<copy_const_t<Const, std::remove_reference_t<F>>&>
0130 >, bool> = true
0131 >
0132 Q_IMPLICIT constexpr function_ref_base(F&& f) noexcept
0133 : m_bound_entity(std::addressof(f)),
0134 m_thunk_ptr([](BoundEntityType ctx, ArgTypes&&... args) noexcept(noex) -> R {
0135 using That = copy_const_t<Const, std::remove_reference_t<F>>;
0136 return q23::invoke_r<R>(*static_cast<That*>(ctx.obj),
0137 std::forward<ArgTypes>(args)...);
0138 })
0139 {}
0140
0141 protected:
0142 template <
0143 class T,
0144 std::enable_if_t<std::negation_v<
0145 std::disjunction<
0146 std::is_same<T, function_ref_base>,
0147 std::is_pointer<T>
0148 >
0149 >, bool> = true
0150 >
0151 function_ref_base& operator=(T) = delete;
0152
0153
0154 R operator()(ArgTypes... args) const noexcept(noex)
0155 {
0156 return m_thunk_ptr(m_bound_entity, std::forward<ArgTypes>(args)...);
0157 }
0158
0159 };
0160
0161 }
0162
0163 #define QT_SPECIALIZE_FUNCTION_REF(cv, noex) \
0164 template<class R, class... ArgTypes> \
0165 class function_ref<R(ArgTypes...) cv noexcept( noex )> \
0166 : private detail::function_ref_base< noex , cv void, R, ArgTypes...> \
0167 { \
0168 using base = detail::function_ref_base< noex , cv void, R, ArgTypes...>; \
0169 \
0170 public: \
0171 using base::base; \
0172 using base::operator(); \
0173 } \
0174
0175
0176 QT_SPECIALIZE_FUNCTION_REF( , false);
0177 QT_SPECIALIZE_FUNCTION_REF(const, false);
0178 QT_SPECIALIZE_FUNCTION_REF( , true );
0179 QT_SPECIALIZE_FUNCTION_REF(const, true );
0180
0181 #undef QT_SPECIALIZE_FUNCTION_REF
0182
0183
0184
0185 template <
0186 class F,
0187 detail::if_function<F> = true
0188 >
0189 function_ref(F*) -> function_ref<F>;
0190
0191 }
0192
0193 QT_END_NAMESPACE
0194
0195 #endif