Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qxpfunctional.h
Go to the documentation of this file.
1// Copyright (C) 2022 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3#ifndef QXPFUNCTIONAL_H
4#define QXPFUNCTIONAL_H
5
6#include <QtCore/qglobal.h>
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. Types and functions defined in this
13// file can reliably be replaced by their std counterparts, once available.
14// You may use these definitions in your own code, but be aware that we
15// will remove them once Qt depends on the C++ version that supports
16// them in namespace std. There will be NO deprecation warning, the
17// definitions will JUST go away.
18//
19// If you can't agree to these terms, don't use these definitions!
20//
21// We mean it.
22//
23
24#include <QtCore/q23functional.h>
25#include <QtCore/q20type_traits.h>
26#include <utility>
27
29
30namespace qxp {
31// like P0792r9's function_ref:
32
33// [func.wrap.ref], non-owning wrapper
34template<class... S> class function_ref; // not defined
35
36// template<class R, class... ArgTypes>
37// class function_ref<R(ArgTypes...) cv noexcept(noex)>; // see below
38//
39// [func.wrap.ref.general]
40// The header provides partial specializations of function_ref for each combination
41// of the possible replacements of the placeholders cv and noex where:
42// - cv is either const or empty.
43// - noex is either true or false.
44
45namespace detail {
46
47template <typename T>
48using if_function = std::enable_if_t<std::is_function_v<T>, bool>;
49template <typename T>
50using if_non_function = std::enable_if_t<!std::is_function_v<T>, bool>;
51
52template <typename From, typename To>
53using copy_const_t = std::conditional_t<
54 std::is_const_v<From>,
55 std::add_const_t<To>,
56 To
57 >;
58
59template <class Const>
61 template <typename F, if_function<F> = true>
62 explicit constexpr BoundEntityType(F *f)
63 : fun(reinterpret_cast<QFunctionPointer>(f)) {}
64 template <typename T, if_non_function<T> = true>
65 explicit constexpr BoundEntityType(T *t)
66 : obj(static_cast<Const*>(t)) {}
67 Const *obj;
68 QFunctionPointer fun;
69};
70
71template <bool noex, class Const, class R, class... ArgTypes>
73{
74protected:
75 ~function_ref_base() = default;
76
78
79 template <typename... Ts>
80 using is_invocable_using = std::conditional_t<
81 noex,
82 std::is_nothrow_invocable_r<R, Ts..., ArgTypes...>,
83 std::is_invocable_r<R, Ts..., ArgTypes...>
84 >;
85
86 using ThunkPtr = R(*)(BoundEntityType, ArgTypes&&...) noexcept(noex);
87
90
91public:
92 template<
93 class F,
94 std::enable_if_t<std::conjunction_v<
95 std::is_function<F>,
96 is_invocable_using<F>
97 >, bool> = true
98 >
100 : m_bound_entity(f),
101 m_thunk_ptr([](BoundEntityType ctx, ArgTypes&&... args) noexcept(noex) -> R {
102 return q23::invoke_r<R>(reinterpret_cast<F*>(ctx.fun),
103 std::forward<ArgTypes>(args)...);
104 })
105 {}
106
107 template<
108 class F,
109 std::enable_if_t<std::conjunction_v<
110 std::negation<std::is_same<q20::remove_cvref_t<F>, function_ref_base>>,
111#ifdef Q_OS_VXWORKS
112 // The VxWorks compiler is trying to match this ctor against
113 // qxp::function_ref in lieu of using the copy-constructor, so ban
114 // matching against the equivalent qxp::function_ref here.
115 // This doesn't change anything on other platforms, so to save
116 // on compile-speed, enable it only for VxWorks:
117 std::negation<
118 std::is_same<
120 std::conditional_t<
121 std::is_const_v<Const>,
122 qxp::function_ref<R(ArgTypes...) const noexcept(noex)>,
123 qxp::function_ref<R(ArgTypes...) noexcept(noex)>
124 >
125 >
126 >,
127#endif // Q_OS_VXWORKS
128 std::negation<std::is_member_pointer<std::remove_reference_t<F>>>,
129 is_invocable_using<copy_const_t<Const, std::remove_reference_t<F>>&>
130 >, bool> = true
131 >
132 Q_IMPLICIT constexpr function_ref_base(F&& f) noexcept
133 : m_bound_entity(std::addressof(f)),
134 m_thunk_ptr([](BoundEntityType ctx, ArgTypes&&... args) noexcept(noex) -> R {
135 using That = copy_const_t<Const, std::remove_reference_t<F>>;
136 return q23::invoke_r<R>(*static_cast<That*>(ctx.obj),
137 std::forward<ArgTypes>(args)...);
138 })
139 {}
140
141protected:
142 template <
143 class T,
144 std::enable_if_t<std::negation_v<
145 std::disjunction<
146 std::is_same<T, function_ref_base>,
147 std::is_pointer<T>
148 >
149 >, bool> = true
150 >
152
153 // Invocation [func.wrap.ref.inv]
154 R operator()(ArgTypes... args) const noexcept(noex)
155 {
156 return m_thunk_ptr(m_bound_entity, std::forward<ArgTypes>(args)...);
157 }
158
159};
160
161} // namespace detail
162
163#define QT_SPECIALIZE_FUNCTION_REF(cv, noex) \
164 template<class R, class... ArgTypes> \
165 class function_ref<R(ArgTypes...) cv noexcept( noex )> \
166 : private detail::function_ref_base< noex , cv void, R, ArgTypes...> \
167 { \
168 using base = detail::function_ref_base< noex , cv void, R, ArgTypes...>; \
169 \
170 public: \
171 using base::base; \
172 using base::operator(); \
173 } \
174 /* end */
175
180
181#undef QT_SPECIALIZE_FUNCTION_REF
182
183// deduction guides [func.wrap.ref.deduct]
184
185template <
186 class F,
188>
189function_ref(F*) -> function_ref<F>;
190
191} // namespace qxp
192
194
195#endif /* QXPFUNCTIONAL_H */
R(*)(BoundEntityType, ArgTypes &&...) noexcept(noex) ThunkPtr
R operator()(ArgTypes... args) const noexcept(noex)
std::conditional_t< noex, std::is_nothrow_invocable_r< R, Ts..., ArgTypes... >, std::is_invocable_r< R, Ts..., ArgTypes... > > is_invocable_using
function_ref_base & operator=(T)=delete
detail::BoundEntityType< Const > BoundEntityType
Q_IMPLICIT constexpr function_ref_base(F &&f) noexcept
Q_IMPLICIT function_ref_base(F *f) noexcept
EGLContext ctx
Combined button and popup list for selecting options.
std::remove_cv_t< std::remove_reference_t< T > > remove_cvref_t
std::enable_if_t< std::is_function_v< T >, bool > if_function
std::conditional_t< std::is_const_v< From >, std::add_const_t< To >, To > copy_const_t
std::enable_if_t<!std::is_function_v< T >, bool > if_non_function
function_ref(F *) -> function_ref< F >
#define Q_IMPLICIT
GLfloat GLfloat f
GLhandleARB obj
[2]
GLdouble GLdouble t
Definition qopenglext.h:243
#define QT_SPECIALIZE_FUNCTION_REF(cv, noex)
QJSValueList args
constexpr BoundEntityType(F *f)
constexpr BoundEntityType(T *t)