Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qnativeinterface.h
Go to the documentation of this file.
1// Copyright (C) 2021 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// Qt-Security score:significant reason:default
4
5#ifndef QNATIVEINTERFACE_H
6#define QNATIVEINTERFACE_H
7
8#include <QtCore/qglobal.h>
9
11
12// We declare a virtual non-inline function in the form
13// of the destructor, making it the key function. This
14// ensures that the typeinfo of the class is exported.
15// By being protected, we also ensure that pointers to
16// the interface can't be deleted.
17#define QT_DECLARE_NATIVE_INTERFACE_3(NativeInterface, Revision, BaseType)
18 protected:
19 virtual ~NativeInterface();
20
21 struct TypeInfo {
22 using baseType = BaseType;
23 static constexpr char const *name = QT_STRINGIFY(NativeInterface);
24 static constexpr int revision = Revision;
25 };
26
27 template <typename, typename>
28 friend struct QNativeInterface::Private::has_type_info;
29
30 template <typename>
31 friend bool constexpr QNativeInterface::Private::hasTypeInfo();
32
33 template <typename>
34 friend struct QNativeInterface::Private::TypeInfo;
35 public:
36 NativeInterface() = default;
37 Q_DISABLE_COPY_MOVE(NativeInterface)
38
39// Revisioned interfaces only make sense when exposed through a base
40// type via QT_DECLARE_NATIVE_INTERFACE_ACCESSOR, as the revision
41// checks happen at that level (and not for normal dynamic_casts).
42#define QT_DECLARE_NATIVE_INTERFACE_2(NativeInterface, Revision)
43 static_assert(false, "Must provide a base type when specifying revision");
44
45#define QT_DECLARE_NATIVE_INTERFACE_1(NativeInterface)
46 QT_DECLARE_NATIVE_INTERFACE_3(NativeInterface, 0, void)
47
48#define QT_DECLARE_NATIVE_INTERFACE(...)
49 QT_OVERLOADED_MACRO(QT_DECLARE_NATIVE_INTERFACE, __VA_ARGS__)
50
51namespace QNativeInterface::Private {
52
53 // Basic type-trait to verify that a given native interface has
54 // all the required type information for us to evaluate it.
55 template <typename NativeInterface, typename = void>
57
58 // The type-trait is friended by TypeInfo, so that we can
59 // evaluate TypeInfo in the template arguments.
60 template <typename NativeInterface>
67
68 // We need to wrap the instantiation of has_type_info in a
69 // function friended by TypeInfo, otherwise MSVC will not
70 // let us evaluate TypeInfo in the template arguments.
71 template <typename NativeInterface>
72 bool constexpr hasTypeInfo()
73 {
74 return has_type_info<NativeInterface>::value;
75 }
76
77 template <typename NativeInterface>
78 struct TypeInfo
79 {
80 // To ensure SFINAE works for hasTypeInfo we can't use it in a constexpr
81 // variable that also includes an expression that relies on the type
82 // info. This helper variable is okey, as it it self contained.
83 static constexpr bool haveTypeInfo = hasTypeInfo<NativeInterface>();
84
85 // We can then use the helper variable in a constexpr condition in a
86 // function, which does not break SFINAE if haveTypeInfo is false.
87 template <typename BaseType>
88 static constexpr bool isCompatibleHelper()
89 {
90 if constexpr (haveTypeInfo)
91 return std::is_base_of<typename NativeInterface::TypeInfo::baseType, BaseType>::value;
92 else
93 return false;
94 }
95
96 // MSVC however doesn't like constexpr functions in enable_if_t conditions,
97 // so we need to wrap it yet again in a constexpr variable. This is fine,
98 // as all the SFINAE magic has been resolved at this point.
99 template <typename BaseType>
100 static constexpr bool isCompatibleWith = isCompatibleHelper<BaseType>();
101
102 // The revision and name accessors are not used in enable_if_t conditions,
103 // so we can leave them as constexpr functions. As this class template is
104 // friended by TypeInfo we can access the protected members of TypeInfo.
105 static constexpr int revision()
106 {
107 if constexpr (haveTypeInfo)
108 return NativeInterface::TypeInfo::revision;
109 else
110 return 0;
111 }
112
113 static constexpr char const *name()
114 {
115 if constexpr (haveTypeInfo)
116 return NativeInterface::TypeInfo::name;
117 else
118 return nullptr;
119 }
120 };
121
122 // Wrapper type to make the error message in case
123 // of incompatible interface types read better.
124 template <typename I>
125 struct NativeInterface : TypeInfo<I> {};
126} // QNativeInterface::Private
127
128// Declares an accessor for the native interface
129#ifdef Q_QDOC
130#define QT_DECLARE_NATIVE_INTERFACE_ACCESSOR(T)
131 template <typename QNativeInterface>
132 QNativeInterface *nativeInterface() const;
133#else
134#define QT_DECLARE_NATIVE_INTERFACE_ACCESSOR(T)
135 template <typename NativeInterface, typename TypeInfo = QNativeInterface::Private::NativeInterface<NativeInterface>,
136 typename BaseType = T, std::enable_if_t<TypeInfo::template isCompatibleWith<T>, bool> = true>
137 NativeInterface *nativeInterface() const
138 {
139 return static_cast<NativeInterface*>(resolveInterface(
140 TypeInfo::name(), TypeInfo::revision()));
141 }
142 protected:
143 void *resolveInterface(const char *name, int revision) const;
144 public:
145#endif
146
147QT_END_NAMESPACE
148
149#endif // QNATIVEINTERFACE_H
Combined button and popup list for selecting options.
constexpr qsizetype lengthHelperPointer(const Char *data) noexcept
QByteArrayView qToByteArrayViewIgnoringNull(const QByteArrayLike &b) noexcept
Q_DECLARE_TYPEINFO(QByteArrayView, Q_PRIMITIVE_TYPE)
#define __has_builtin(x)
Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher")
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION unsigned int qt_int_sqrt(unsigned int n)
\inmodule QtCore \title Global Qt Declarations
Definition qglobal.cpp:100
#define QT_DECLARE_NATIVE_INTERFACE(...)
#define QT_DECLARE_NATIVE_INTERFACE_3(NativeInterface, Revision, BaseType)
QList< QList< qInternalCallback > > callbacks
Definition qglobal.cpp:129
static constexpr char const * name()
static constexpr bool isCompatibleHelper()