Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/QtCore/qnativeinterface.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 // Copyright (C) 2021 The Qt Company Ltd.
0002 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
0003 
0004 #ifndef QNATIVEINTERFACE_H
0005 #define QNATIVEINTERFACE_H
0006 
0007 #include <QtCore/qglobal.h>
0008 
0009 QT_BEGIN_NAMESPACE
0010 
0011 // We declare a virtual non-inline function in the form
0012 // of the destructor, making it the key function. This
0013 // ensures that the typeinfo of the class is exported.
0014 // By being protected, we also ensure that pointers to
0015 // the interface can't be deleted.
0016 #define QT_DECLARE_NATIVE_INTERFACE_3(NativeInterface, Revision, BaseType) \
0017     protected: \
0018         virtual ~NativeInterface(); \
0019         \
0020         struct TypeInfo { \
0021             using baseType = BaseType; \
0022             static constexpr char const *name = QT_STRINGIFY(NativeInterface); \
0023             static constexpr int revision = Revision; \
0024         }; \
0025         \
0026         template <typename, typename> \
0027         friend struct QNativeInterface::Private::has_type_info; \
0028         \
0029         template <typename> \
0030         friend bool constexpr QNativeInterface::Private::hasTypeInfo(); \
0031         \
0032         template <typename> \
0033         friend struct QNativeInterface::Private::TypeInfo; \
0034     public: \
0035         NativeInterface() = default; \
0036         Q_DISABLE_COPY_MOVE(NativeInterface)
0037 
0038 // Revisioned interfaces only make sense when exposed through a base
0039 // type via QT_DECLARE_NATIVE_INTERFACE_ACCESSOR, as the revision
0040 // checks happen at that level (and not for normal dynamic_casts).
0041 #define QT_DECLARE_NATIVE_INTERFACE_2(NativeInterface, Revision) \
0042     static_assert(false, "Must provide a base type when specifying revision");
0043 
0044 #define QT_DECLARE_NATIVE_INTERFACE_1(NativeInterface) \
0045     QT_DECLARE_NATIVE_INTERFACE_3(NativeInterface, 0, void)
0046 
0047 #define QT_DECLARE_NATIVE_INTERFACE(...) \
0048     QT_OVERLOADED_MACRO(QT_DECLARE_NATIVE_INTERFACE, __VA_ARGS__)
0049 
0050 namespace QNativeInterface::Private {
0051 
0052     // Basic type-trait to verify that a given native interface has
0053     // all the required type information for us to evaluate it.
0054     template <typename NativeInterface, typename = void>
0055     struct has_type_info : std::false_type {};
0056 
0057     // The type-trait is friended by TypeInfo, so that we can
0058     // evaluate TypeInfo in the template arguments.
0059     template <typename NativeInterface>
0060     struct has_type_info<NativeInterface, std::void_t<
0061         typename NativeInterface::TypeInfo,
0062         typename NativeInterface::TypeInfo::baseType,
0063         decltype(&NativeInterface::TypeInfo::name),
0064         decltype(&NativeInterface::TypeInfo::revision)
0065         >> : std::true_type {};
0066 
0067     // We need to wrap the instantiation of has_type_info in a
0068     // function friended by TypeInfo, otherwise MSVC will not
0069     // let us evaluate TypeInfo in the template arguments.
0070     template <typename NativeInterface>
0071     bool constexpr hasTypeInfo()
0072     {
0073         return has_type_info<NativeInterface>::value;
0074     }
0075 
0076     template <typename NativeInterface>
0077     struct TypeInfo
0078     {
0079         // To ensure SFINAE works for hasTypeInfo we can't use it in a constexpr
0080         // variable that also includes an expression that relies on the type
0081         // info. This helper variable is okey, as it it self contained.
0082         static constexpr bool haveTypeInfo = hasTypeInfo<NativeInterface>();
0083 
0084         // We can then use the helper variable in a constexpr condition in a
0085         // function, which does not break SFINAE if haveTypeInfo is false.
0086         template <typename BaseType>
0087         static constexpr bool isCompatibleHelper()
0088         {
0089             if constexpr (haveTypeInfo)
0090                 return std::is_base_of<typename NativeInterface::TypeInfo::baseType, BaseType>::value;
0091             else
0092                 return false;
0093         }
0094 
0095         // MSVC however doesn't like constexpr functions in enable_if_t conditions,
0096         // so we need to wrap it yet again in a constexpr variable. This is fine,
0097         // as all the SFINAE magic has been resolved at this point.
0098         template <typename BaseType>
0099         static constexpr bool isCompatibleWith = isCompatibleHelper<BaseType>();
0100 
0101         // The revision and name accessors are not used in enable_if_t conditions,
0102         // so we can leave them as constexpr functions. As this class template is
0103         // friended by TypeInfo we can access the protected members of TypeInfo.
0104         static constexpr int revision()
0105         {
0106             if constexpr (haveTypeInfo)
0107                 return NativeInterface::TypeInfo::revision;
0108             else
0109                 return 0;
0110         }
0111 
0112         static constexpr char const *name()
0113         {
0114             if constexpr (haveTypeInfo)
0115                 return NativeInterface::TypeInfo::name;
0116             else
0117                 return nullptr;
0118         }
0119     };
0120 
0121     // Wrapper type to make the error message in case
0122     // of incompatible interface types read better.
0123     template <typename I>
0124     struct NativeInterface : TypeInfo<I> {};
0125 } // QNativeInterface::Private
0126 
0127 // Declares an accessor for the native interface
0128 #ifdef Q_QDOC
0129 #define QT_DECLARE_NATIVE_INTERFACE_ACCESSOR(T) \
0130     template <typename QNativeInterface> \
0131     QNativeInterface *nativeInterface() const;
0132 #else
0133 #define QT_DECLARE_NATIVE_INTERFACE_ACCESSOR(T) \
0134     template <typename NativeInterface, typename TypeInfo = QNativeInterface::Private::NativeInterface<NativeInterface>, \
0135     typename BaseType = T, std::enable_if_t<TypeInfo::template isCompatibleWith<T>, bool> = true> \
0136     NativeInterface *nativeInterface() const \
0137     { \
0138         return static_cast<NativeInterface*>(resolveInterface( \
0139             TypeInfo::name(), TypeInfo::revision())); \
0140     } \
0141     protected: \
0142         void *resolveInterface(const char *name, int revision) const; \
0143     public:
0144 #endif
0145 
0146 QT_END_NAMESPACE
0147 
0148 #endif // QNATIVEINTERFACE_H