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