Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-01-09 10:22:12

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