QtBase  v6.3.1
qnativeinterface.h
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2021 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #ifndef QNATIVEINTERFACE_H
41 #define QNATIVEINTERFACE_H
42 
43 #include <QtCore/qglobal.h>
44 
46 
47 // We declare a virtual non-inline function in the form
48 // of the destructor, making it the key function. This
49 // ensures that the typeinfo of the class is exported.
50 // By being protected, we also ensure that pointers to
51 // the interface can't be deleted.
52 #define QT_DECLARE_NATIVE_INTERFACE_3(NativeInterface, Revision, BaseType) \
53  protected: \
54  virtual ~NativeInterface(); \
55  \
56  struct TypeInfo { \
57  using baseType = BaseType; \
58  static constexpr char const *name = QT_STRINGIFY(NativeInterface); \
59  static constexpr int revision = Revision; \
60  }; \
61  \
62  template <typename, typename> \
63  friend struct QNativeInterface::Private::has_type_info; \
64  \
65  template <typename> \
66  friend bool constexpr QNativeInterface::Private::hasTypeInfo(); \
67  \
68  template <typename> \
69  friend struct QNativeInterface::Private::TypeInfo; \
70  public: \
71  NativeInterface() = default; \
72  Q_DISABLE_COPY_MOVE(NativeInterface)
73 
74 // Revisioned interfaces only make sense when exposed through a base
75 // type via QT_DECLARE_NATIVE_INTERFACE_ACCESSOR, as the revision
76 // checks happen at that level (and not for normal dynamic_casts).
77 #define QT_DECLARE_NATIVE_INTERFACE_2(NativeInterface, Revision) \
78  static_assert(false, "Must provide a base type when specifying revision");
79 
80 #define QT_DECLARE_NATIVE_INTERFACE_1(NativeInterface) \
81  QT_DECLARE_NATIVE_INTERFACE_3(NativeInterface, 0, void)
82 
83 #define QT_DECLARE_NATIVE_INTERFACE(...) \
84  QT_OVERLOADED_MACRO(QT_DECLARE_NATIVE_INTERFACE, __VA_ARGS__)
85 
87 
88  // Basic type-trait to verify that a given native interface has
89  // all the required type information for us to evaluate it.
90  template <typename NativeInterface, typename = void>
91  struct has_type_info : std::false_type {};
92 
93  // The type-trait is friended by TypeInfo, so that we can
94  // evaluate TypeInfo in the template arguments.
95  template <typename NativeInterface>
97  typename NativeInterface::TypeInfo,
98  typename NativeInterface::TypeInfo::baseType,
99  decltype(&NativeInterface::TypeInfo::name),
100  decltype(&NativeInterface::TypeInfo::revision)
101  >> : std::true_type {};
102 
103  // We need to wrap the instantiation of has_type_info in a
104  // function friended by TypeInfo, otherwise MSVC will not
105  // let us evaluate TypeInfo in the template arguments.
106  template <typename NativeInterface>
107  bool constexpr hasTypeInfo()
108  {
110  }
111 
112  template <typename NativeInterface>
113  struct TypeInfo
114  {
115  // To ensure SFINAE works for hasTypeInfo we can't use it in a constexpr
116  // variable that also includes an expression that relies on the type
117  // info. This helper variable is okey, as it it self contained.
118  static constexpr bool haveTypeInfo = hasTypeInfo<NativeInterface>();
119 
120  // We can then use the helper variable in a constexpr condition in a
121  // function, which does not break SFINAE if haveTypeInfo is false.
122  template <typename BaseType>
123  static constexpr bool isCompatibleHelper()
124  {
125  if constexpr (haveTypeInfo)
127  else
128  return false;
129  }
130 
131  // MSVC however doesn't like constexpr functions in enable_if_t conditions,
132  // so we need to wrap it yet again in a constexpr variable. This is fine,
133  // as all the SFINAE magic has been resolved at this point.
134  template <typename BaseType>
135  static constexpr bool isCompatibleWith = isCompatibleHelper<BaseType>();
136 
137  // The revision and name accessors are not used in enable_if_t conditions,
138  // so we can leave them as constexpr functions. As this class template is
139  // friended by TypeInfo we can access the protected members of TypeInfo.
140  static constexpr int revision()
141  {
142  if constexpr (haveTypeInfo)
143  return NativeInterface::TypeInfo::revision;
144  else
145  return 0;
146  }
147 
148  static constexpr char const *name()
149  {
150  if constexpr (haveTypeInfo)
152  else
153  return nullptr;
154  }
155  };
156 
157  // Wrapper type to make the error message in case
158  // of incompatible interface types read better.
159  template <typename I>
160  struct NativeInterface : TypeInfo<I> {};
161 } // QNativeInterface::Private
162 
163 // Declares an accessor for the native interface
164 #ifdef Q_QDOC
165 #define QT_DECLARE_NATIVE_INTERFACE_ACCESSOR(T) \
166  template <typename QNativeInterface> \
167  QNativeInterface *nativeInterface() const;
168 #else
169 #define QT_DECLARE_NATIVE_INTERFACE_ACCESSOR(T) \
170  template <typename NativeInterface, typename TypeInfo = QNativeInterface::Private::NativeInterface<NativeInterface>, \
171  typename BaseType = T, std::enable_if_t<TypeInfo::template isCompatibleWith<T>, bool> = true> \
172  NativeInterface *nativeInterface() const \
173  { \
174  return static_cast<NativeInterface*>(resolveInterface( \
175  TypeInfo::name(), TypeInfo::revision())); \
176  } \
177  protected: \
178  void *resolveInterface(const char *name, int revision) const; \
179  public:
180 #endif
181 
183 
184 #endif // QNATIVEINTERFACE_H
#define value
[5]
constexpr bool hasTypeInfo()
Definition: qfloat16.h:381
GLuint name
static constexpr char const * name()
static constexpr bool isCompatibleHelper()
static constexpr bool isCompatibleWith