Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-10-26 08:53:28

0001 // Copyright (C) 2016 The Qt Company Ltd.
0002 // Copyright (C) 2016 Intel Corporation.
0003 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
0004 
0005 #ifndef QTYPEINFO_H
0006 #define QTYPEINFO_H
0007 
0008 #include <QtCore/qcompilerdetection.h>
0009 #include <QtCore/qcontainerfwd.h>
0010 
0011 #include <type_traits>
0012 
0013 QT_BEGIN_NAMESPACE
0014 
0015 class QDebug;
0016 
0017 /*
0018    QTypeInfo     - type trait functionality
0019 */
0020 
0021 namespace QtPrivate {
0022 
0023 // A trivially copyable class must also have a trivial, non-deleted
0024 // destructor [class.prop/1.3], CWG1734. Some implementations don't
0025 // check for a trivial destructor, because of backwards compatibility
0026 // with C++98's definition of trivial copyability.
0027 // Since trivial copiability has implications for the ABI, implementations
0028 // can't "just fix" their traits. So, although formally redundant, we
0029 // explicitly check for trivial destruction here.
0030 template <typename T>
0031 inline constexpr bool qIsRelocatable =  std::is_trivially_copyable_v<T> && std::is_trivially_destructible_v<T>;
0032 
0033 // Denotes types that are trivially default constructible, and for which
0034 // value-initialization can be achieved by filling their storage with 0 bits.
0035 // There is no type trait we can use for this, so we hardcode a list of
0036 // possibilities that we know are OK on the architectures that we support.
0037 // The most notable exception are pointers to data members, which for instance
0038 // on the Itanium ABI are initialized to -1.
0039 template <typename T>
0040 inline constexpr bool qIsValueInitializationBitwiseZero =
0041         std::is_scalar_v<T> && !std::is_member_object_pointer_v<T>;
0042 
0043 }
0044 
0045 /*
0046   The catch-all template.
0047 */
0048 
0049 template <typename T>
0050 class QTypeInfo
0051 {
0052 public:
0053     enum {
0054         isPointer [[deprecated("Use std::is_pointer instead")]] = std::is_pointer_v<T>,
0055         isIntegral [[deprecated("Use std::is_integral instead")]] = std::is_integral_v<T>,
0056         isComplex = !std::is_trivial_v<T>,
0057         isRelocatable = QtPrivate::qIsRelocatable<T>,
0058         isValueInitializationBitwiseZero = QtPrivate::qIsValueInitializationBitwiseZero<T>,
0059     };
0060 };
0061 
0062 template<>
0063 class QTypeInfo<void>
0064 {
0065 public:
0066     enum {
0067         isPointer [[deprecated("Use std::is_pointer instead")]] = false,
0068         isIntegral [[deprecated("Use std::is_integral instead")]] = false,
0069         isComplex = false,
0070         isRelocatable = false,
0071         isValueInitializationBitwiseZero = false,
0072     };
0073 };
0074 
0075 /*!
0076     \class QTypeInfoMerger
0077     \inmodule QtCore
0078     \internal
0079 
0080     \brief QTypeInfoMerger merges the QTypeInfo flags of T1, T2... and presents them
0081     as a QTypeInfo<T> would do.
0082 
0083     Let's assume that we have a simple set of structs:
0084 
0085     \snippet code/src_corelib_global_qglobal.cpp 50
0086 
0087     To create a proper QTypeInfo specialization for A struct, we have to check
0088     all sub-components; B, C and D, then take the lowest common denominator and call
0089     Q_DECLARE_TYPEINFO with the resulting flags. An easier and less fragile approach is to
0090     use QTypeInfoMerger, which does that automatically. So struct A would have
0091     the following QTypeInfo definition:
0092 
0093     \snippet code/src_corelib_global_qglobal.cpp 51
0094 */
0095 template <class T, class...Ts>
0096 class QTypeInfoMerger
0097 {
0098     static_assert(sizeof...(Ts) > 0);
0099 public:
0100     static constexpr bool isComplex = ((QTypeInfo<Ts>::isComplex) || ...);
0101     static constexpr bool isRelocatable = ((QTypeInfo<Ts>::isRelocatable) && ...);
0102     [[deprecated("Use std::is_pointer instead")]] static constexpr bool isPointer = false;
0103     [[deprecated("Use std::is_integral instead")]] static constexpr bool isIntegral = false;
0104     static constexpr bool isValueInitializationBitwiseZero = false;
0105     static_assert(!isRelocatable ||
0106                   std::is_copy_constructible_v<T> ||
0107                   std::is_move_constructible_v<T>,
0108                   "All Ts... are Q_RELOCATABLE_TYPE, but T is neither copy- nor move-constructible, "
0109                   "so cannot be Q_RELOCATABLE_TYPE. Please mark T as Q_COMPLEX_TYPE manually.");
0110 };
0111 
0112 // QTypeInfo for std::pair:
0113 //   std::pair is spec'ed to be struct { T1 first; T2 second; }, so, unlike tuple<>,
0114 //   we _can_ specialize QTypeInfo for pair<>:
0115 template <class T1, class T2>
0116 class QTypeInfo<std::pair<T1, T2>> : public QTypeInfoMerger<std::pair<T1, T2>, T1, T2> {};
0117 
0118 #define Q_DECLARE_MOVABLE_CONTAINER(CONTAINER) \
0119 template <typename ...T> \
0120 class QTypeInfo<CONTAINER<T...>> \
0121 { \
0122 public: \
0123     enum { \
0124         isPointer [[deprecated("Use std::is_pointer instead")]] = false, \
0125         isIntegral [[deprecated("Use std::is_integral instead")]] = false, \
0126         isComplex = true, \
0127         isRelocatable = true, \
0128         isValueInitializationBitwiseZero = false, \
0129     }; \
0130 }
0131 
0132 Q_DECLARE_MOVABLE_CONTAINER(QList);
0133 Q_DECLARE_MOVABLE_CONTAINER(QQueue);
0134 Q_DECLARE_MOVABLE_CONTAINER(QStack);
0135 Q_DECLARE_MOVABLE_CONTAINER(QSet);
0136 Q_DECLARE_MOVABLE_CONTAINER(QMap);
0137 Q_DECLARE_MOVABLE_CONTAINER(QMultiMap);
0138 Q_DECLARE_MOVABLE_CONTAINER(QHash);
0139 Q_DECLARE_MOVABLE_CONTAINER(QMultiHash);
0140 Q_DECLARE_MOVABLE_CONTAINER(QCache);
0141 
0142 #undef Q_DECLARE_MOVABLE_CONTAINER
0143 
0144 /*
0145    Specialize a specific type with:
0146 
0147      Q_DECLARE_TYPEINFO(type, flags);
0148 
0149    where 'type' is the name of the type to specialize and 'flags' is
0150    logically-OR'ed combination of the flags below.
0151 */
0152 enum { /* TYPEINFO flags */
0153     Q_COMPLEX_TYPE = 0,
0154     Q_PRIMITIVE_TYPE = 0x1,
0155     Q_RELOCATABLE_TYPE = 0x2,
0156     Q_MOVABLE_TYPE = 0x2,
0157     Q_DUMMY_TYPE = 0x4,
0158 };
0159 
0160 #define Q_DECLARE_TYPEINFO_BODY(TYPE, FLAGS) \
0161 class QTypeInfo<TYPE > \
0162 { \
0163 public: \
0164     enum { \
0165         isComplex = (((FLAGS) & Q_PRIMITIVE_TYPE) == 0) && !std::is_trivial_v<TYPE>, \
0166         isRelocatable = !isComplex || ((FLAGS) & Q_RELOCATABLE_TYPE) || QtPrivate::qIsRelocatable<TYPE>, \
0167         isPointer [[deprecated("Use std::is_pointer instead")]] = std::is_pointer_v< TYPE >, \
0168         isIntegral [[deprecated("Use std::is_integral instead")]] = std::is_integral< TYPE >::value, \
0169         isValueInitializationBitwiseZero = QtPrivate::qIsValueInitializationBitwiseZero<TYPE>, \
0170     }; \
0171     static_assert(!QTypeInfo<TYPE>::isRelocatable || \
0172                   std::is_copy_constructible_v<TYPE > || \
0173                   std::is_move_constructible_v<TYPE >, \
0174                   #TYPE " is neither copy- nor move-constructible, so cannot be Q_RELOCATABLE_TYPE"); \
0175 }
0176 
0177 #define Q_DECLARE_TYPEINFO(TYPE, FLAGS) \
0178 template<> \
0179 Q_DECLARE_TYPEINFO_BODY(TYPE, FLAGS)
0180 
0181 /* Specialize QTypeInfo for QFlags<T> */
0182 template<typename T> class QFlags;
0183 template<typename T>
0184 Q_DECLARE_TYPEINFO_BODY(QFlags<T>, Q_PRIMITIVE_TYPE);
0185 
0186 QT_END_NAMESPACE
0187 #endif // QTYPEINFO_H