当前位置: 首页 > news >正文

QT6 源(93)篇三:阅读与注释共用体类 QVariant 及其源代码,本类支持比较运算符 ==、!=。

(9) 本类支持比较运算符 ==、!=

在这里插入图片描述

++可见, QString 类型里可存储多个 unicode 字符,即使只存储一个 unicode 字符也不等于 QChar

(10)本源代码来自于头文件 qvariant . h

#ifndef QVARIANT_H
#define QVARIANT_H#include <QtCore/qatomic.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qlist.h>
#include <QtCore/qmetatype.h>
#include <QtCore/qmap.h>
#include <QtCore/qhash.h>
#include <QtCore/qstring.h>
#include <QtCore/qstringlist.h>
#include <QtCore/qobject.h>
#ifndef QT_NO_DEBUG_STREAM
#include <QtCore/qdebug.h>
#endif
#ifndef QT_BOOTSTRAPPED
#include <QtCore/qbytearraylist.h>
#endif
#include <memory>
#include <type_traits>#if __has_include(<variant>) && __cplusplus >= 201703L
#include <variant>
#elif defined(Q_CLANG_QDOC)
namespace std { template<typename...> struct variant; }
#endifQT_BEGIN_NAMESPACEclass QBitArray;
class QDataStream;
class QDate;
class QDateTime;#if QT_CONFIG(easingcurve)class QEasingCurve;
#endifclass QLine;
class QLineF;
class QLocale;
class QTransform;
class QTime;
class QPoint;
class QPointF;
class QSize;
class QSizeF;
class QRect;
class QRectF;#if QT_CONFIG(regularexpression)class QRegularExpression;
#endif // QT_CONFIG(regularexpression)class QTextFormat;
class QTextLength;
class QUrl;
class QVariant;#ifndef QT_NO_DATASTREAM
Q_CORE_EXPORT QDataStream & operator >>(QDataStream & s,       QVariant & p);
Q_CORE_EXPORT QDataStream & operator <<(QDataStream & s, const QVariant & p);
#endiftemplate<typename T> //先来一个全局模板函数。函数声明
inline T qvariant_cast(const QVariant &);#ifndef QT_MOC  //下面的函数是存在的
template<typename T>
inline T qvariant_cast(const QVariant & v)
{QMetaType targetType = QMetaType::fromType<T>();if (v.d.type() == targetType)return v.d.get<T>();if constexpr (std::is_same_v<T,std::remove_const_t<std::remove_pointer_t<T>> const *>){using nonConstT = std::remove_const_t<std::remove_pointer_t<T>> *;QMetaType nonConstTargetType = QMetaType::fromType<nonConstT>();if (v.d.type() == nonConstTargetType)return v.d.get<nonConstT>();}T t{}; //定义一个空值,填充后返回QMetaType::convert(v.metaType(), v.constData(), targetType, & t);return t;
}template<>  //模板特化
inline QVariant qvariant_cast<QVariant>(const QVariant & v)
{if (v.metaType().id() == QMetaType::QVariant)return * reinterpret_cast<const QVariant *>(v.constData());return v;
}
#endif/*
The QVariant class acts like a union for the most common Qt data types.由于C++禁止联合体包含具有非默认构造函数或析构函数的类型,因此大多数有趣的 Qt类不能在联合体中使用。
如果没有QVariant,这将给 Q0bject::property()和数据库工作等带来问题。QVariant对象一次只能持有单个类型的一个值(某些类型是多值的,例如字符串列表)。
你可以找出该变体持有的类型T,使用convert()将其转换为不同的类型,
使用toT()函数之-(例如toSize())获取其值,
并使用canConvert()检查该类型是否可以转换为特定类型。
名为 toT()的方法(例如 tolnt()和 toString())是常量。
如果您询问存储的类型,它们会返回存储对象的副本。
如果您询问可以从存储类型生成的类型,toT()会复制、转换并保留对象本身不变。
如果您询问无法从存储类型生成的类型,结果取决于类型;请查看函数文档以获取详细信息。你甚至可以将 QList<QVariant>和 QMap<QString,QVariant>值存储在一个变体中,
因此你可以轻松构建任意类型的任意复杂数据结构。
这非常强大和通用,但可能不如在标准数据结构中存储特定类型那样节省内存和提高速度。QVariant还支持空值的概念。如果变量不包含初始化值,或者包含空指针,则变量为null。QVariant 可以扩展以支持除 QMetaType::Type 枚举中提到的类型以外的其他类型。
有关详细信息,请参阅创建自定义 Qt 类型。enum QMetaType::Type {      //定义了一个类内部的枚举类型// these are merged with QVariantQT_FOR_EACH_STATIC_TYPE(QT_DEFINE_METATYPE_ID)FirstCoreType     = Bool,         //=  1LastCoreType     = QVariantPair, //= 58FirstGuiType      = QFont,       //=0x1000LastGuiType      = QColorSpace, //=0x1017FirstWidgetsType  = QSizePolicy, //=0x2000LastWidgetsType  = QSizePolicy, //=0x2000HighestInternalId = LastWidgetsType, //=0x2000QReal = sizeof(qreal) == sizeof(double) ? Double : Float,//这里是在依托机器平台定义浮点数的默认类型UnknownType       = 0,User              = 65536};A Note on GUI Types:
因为 QVariant是 Qt Core 模块的一部分,所以它不能为 Qt GU 中定义的数据类型提供转换函数,
例如QColor、Qimage和 QPixmap。换句话说,没有toColor()函数。
相反,您可以使用 QVariant::value() 或模板函数 qvariant_cast()。例如:QVariant variant;...QColor color = variant.value<QColor>();到 QVariant)的反向转换是自动的(例如从 QColor),
对于 QVariant 支持的所有数据类型(包括与 GUl相关的类型):QColor color = palette().background().color();QVariant variant = color;Using canConvert() and convert() Consecutively连续地 :
当连续使用canConvert()和convert()时,canConvert()可能返回 true,但convert()返回 false。
这通常是因为 canConvert()只报告 QVariant 在给定合适数据时转换类型的一般能力;
仍然有可能提供实际上无法转换的数据。例如,当对包含字符串的变体调用 canConvert(QMetaType::fromType<int>())时,它会返回 true,
因为原则上 QVariant 能够将字符串和数字转换为整数。
但是,如果字符串包含非数字字符,则无法将其转换为整数,任何尝试转换的尝试都将失败。
因此,重要的是两个数都返回 true 以表示成功转换。*/class Q_CORE_EXPORT QVariant  //正类开始定义
{  
public: //这里首先定义了两个类中类。这是为了辅助本类中的数据成员的定义struct PrivateShared{private:inline PrivateShared() : ref(1) { }//私有构造函数public:alignas(8) QAtomicInt ref;// 8字节对齐的原子整数int offset; //本类的数据成员,一个整数,起名叫偏移量static PrivateShared * create( //本类的静态成员函数const QtPrivate::QMetaTypeInterface * type){Q_ASSERT(type);size_t size  = type->size;size_t align = type->alignment;size += sizeof(PrivateShared);if (align > sizeof(PrivateShared)) {//The alignment is larger than the alignment we can guarantee//for the pointer directly following PrivateShared,//该对齐大于我们可以为直接跟随 PrivateShared的指针保证的对齐,//so we need to allocate some additional memory to be able to//fit the object into the available memory//with suitable alignment.//因此我们需要分配一些额外的内存,以便能够将对象适合到可用内存中,//并具有适当的对齐。size += align - sizeof(PrivateShared);}void * data = operator new(size); //分配了内存auto * ps   = new (data) QVariant::PrivateShared();//在 ps 指针处构造了本类对象 QVariant::PrivateSharedps->offset  = int( ((quintptr(ps) + sizeof(PrivateShared) + align - 1) &~(align - 1)) - quintptr(ps)  );return ps;}static void free(PrivateShared * p) //静态的释放函数对应 create(){   p-> ~PrivateShared(); //执行了析构函数后,释放本类对象占据的内存operator delete(p)  ;}const void * data() const //函数重载{ return reinterpret_cast<const unsigned char *>(this)+ offset; //把本类对象的地址加上 offset 偏移量后返回}void * data(){ return reinterpret_cast<unsigned char *>(this) + offset; }}; //完结 struct PrivateSharedstruct Private  //又定义了这个类中类{   //先定义了一个静态的类内数据成员,3 个指针大小,目前是 24 字节static constexpr size_t MaxInternalSize = 3 * sizeof(void *);template<typename T>  //又定义了这个静态的类内数据成员,还是模板变量static constexpr bool CanUseInternalSpace = ( //这是个布尔量QTypeInfo<T>::isRelocatable  && //此布尔值sizeof(T) <= MaxInternalSize && //是三个与操作alignof(T) <= alignof(double)  ); //的结果union  //这是共用体,大小取最大的成员的类型的大小{   uchar data[MaxInternalSize] = {}; //定义 24字节的数组PrivateShared       *   shared  ; //定义一个指针变量double            _forAlignment ; //定义一个 double 成员// we want an 8byte alignment on 32bit systems as well} data; //此处为本类定义了一个 union 类型的数据成员,名字叫 dataquintptr is_shared  : 1;quintptr is_null    : 1; //这里又有三个整数成员quintptr packedType : sizeof(QMetaType) * 8 - 2;//静态成员函数,返回值是布尔量。看是否可以用内部空间的意思。static constexpr bool canUseInternalSpace(QtPrivate::QMetaTypeInterface *type){Q_ASSERT(type);return QMetaType::TypeFlags(type->flags) &QMetaType::RelocatableType &&size_t(type->size) <= MaxInternalSize &&size_t(type->alignment) <= alignof(double);}Private() noexcept : //本类的默认无参构造函数is_shared(false), is_null(true), packedType(0) {}explicit Private(QMetaType type) noexcept //有参构造函数: is_shared(false), is_null(false){quintptr mt = quintptr(type.d_ptr);Q_ASSERT((mt & 0x3) == 0);packedType = mt >> 2;}//似乎是构造函数又调用了构造函数explicit Private(int type) noexcept: Private(QMetaType(type)) {}//返回存储区的起始地址的意思const void * storage() const{ return                 is_shared ?data.shared->data() :& data.data; }//返回内部存储区的起始地址const void * internalStorage() const{   Q_ASSERT(is_shared);return & data.data;}// determine internal storage at compile timetemplate<typename T> //模板成员函数,返回左值引用const T & get() const{ return * static_cast<const T *>(storage()); }template<typename T> //接受赋值void set(const T & t){   *static_cast<T *>(CanUseInternalSpace<T> ?&  data.data :data.shared->data()) = t;}inline QMetaType type() const{   //返回 QmetaType 类型return QMetaType(reinterpret_cast<QtPrivate::QMetaTypeInterface *>(packedType << 2));}inline int typeId() const { return type().id(); }inline QtPrivate::QMetaTypeInterface * //返回指针类型typeInterface() const{return reinterpret_cast<QtPrivate::QMetaTypeInterface *>(packedType << 2);}}; //完结 struct Privateprotected :Private d;   //此处定义了本类的数据成员,名字叫 d//以下保护权限的成员函数,都没有官方注释void create(int type, const void *copy);void create(QMetaType type, const void *copy);bool equals(const QVariant &other) const;bool convert(int type, void *ptr) const;bool view(int type, void *ptr);public:typedef Private DataPtr; //为类名称起个新名称inline       DataPtr & data_ptr()       { return d; }inline const DataPtr & data_ptr() const { return d; }//Returns a pointer to the contained object//as a generic void* that can be written to.//This function detaches the QVariant.//When called on a null-QVariant,//the QVariant will not be null after the call.void  *      data();inline const    void  *      data() const { return constData(); }const           void  * constData() const { return d.storage(); }public : //重点开始QVariant() noexcept : d() {} //默认构造函数~QVariant(); //本类的虚析构函数//本类的有参构造函数explicit QVariant(QMetaType type, const void * copy = nullptr);QVariant(const QVariant & other); //本类的 copy 构造函数QVariant(int          i);  //以下的构造函数表明,QVariant(uint        ui);  //本类可以接受一个普通数据,QVariant(qlonglong   ll);  //并完成构造与对象创建QVariant(qulonglong ull);QVariant(bool         b);QVariant(double       d);QVariant(float        f);//说明可以以字符串构造本对象QVariant(const char * str) : QVariant(QString::fromUtf8(str)) {}QVariant(const QByteArray & bytearray); //构造函数QVariant(const QBitArray  & bitarray );//说明可以以 QString 对象来构造本 QVariant 对象QVariant(const QString    & string);QVariant(QLatin1String      string);//拉丁文//容器里存储了多个字符串,说明可以拿容器对象来构造本 QVariant//using QStringList = QList<QString>;QVariant(const QStringList & stringlist);QVariant(QChar qchar);QVariant(QDate date) ; //以日期对象来构造本对象QVariant(QTime time) ; //以时间对象来构造本对象QVariant(const QDateTime & datetime);//再次以 QList、QMap、QHash容器对象来构造本对象//但要求键值对必须是 <字符串,QVariant> 形式QVariant(const QList<QVariant> &list);    QVariant(const QMap<QString , QVariant> & map );QVariant(const QHash<QString, QVariant> & hash);#ifndef QT_NO_GEOM_VARIANT //经验证,确实没定义此宏QVariant(const QSize  & size);  //这些函数都被定义了//Constructs a new variant with a size value of val.QVariant(const QSizeF & size);//Constructs a new variant with a point value of val.QVariant(const QPoint  & pt);QVariant(const QPointF & pt);//Constructs a new variant with a line value of val.QVariant(const QLine  & line);QVariant(const QLineF & line);//Constructs a new variant with a rect value of val.QVariant(const QRect  & rect);QVariant(const QRectF & rect);
#endif//Constructs a new variant with a locale value, l.QVariant(const QLocale & locale);QVariant(const QUuid   & uuid);//宏定义中的##是预处理器的标记粘贴操作符,会把前后的标记连接起来。
//如feature是Thread,
//则QT_FEATURE_##feature就会拼接成QT_FEATURE_Thread
//通过除 0 错误来完成编译检查
//#define  QT_CONFIG(feature)  (1/QT_FEATURE_##feature == 1)
#if QT_CONFIG(regularexpression) //经验证允许正则表达式QVariant(const QRegularExpression & re);
#endif // QT_CONFIG(regularexpression)#if QT_CONFIG(easingcurve) //缓和曲线 easingcurveQVariant(const QEasingCurve & easing);
#endif#ifndef QT_BOOTSTRAPPED //似乎是用于 json 处理领域QVariant(const QUrl          & url         );QVariant(const QJsonValue    & jsonValue   );QVariant(const QJsonObject   & jsonObject  );QVariant(const QJsonArray    & jsonArray   );QVariant(const QJsonDocument & jsonDocument);
#endif // QT_BOOTSTRAPPED#if QT_CONFIG(itemmodel)  //有此定义的QVariant(const QModelIndex           & modelIndex);QVariant(const QPersistentModelIndex & modelIndex);
#endif//定义了本类的 copy 赋值运算符函数QVariant & operator=(const QVariant & other);//本类的移动构造函数inline QVariant(QVariant && other) noexcept : d(other.d){ other.d = Private(); }//看起来是以宏的形式,定义了本类的 移动赋值运算符函数QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QVariant)
//#define QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(Class) \
//    Class &operator=(Class &&other) noexcept { \
//            Class moved(std::move(other)); \
//            swap(moved); \
//            return *this; \
//    }//与另一个 QVariant 对象进行交换数据的操作inline void swap(QVariant & other) noexcept{ qSwap(d, other.d); }//返回存储在变体中的值的 QMetaType。//本 QMetaType 已粗略整理源系列(7)以后再详细整理QMetaType metaType() const; //逐次往下调用//返回存储在本对象中的值的存储类型。这与metaType().id()相同。int typeId  () const { return metaType().id(); }// QT 里确实对各种数据类型按整数进行了类型区分,故返回整数。int userType() const { return typeId(); }//对于QString 类型则返回 10//返回存储在变体中的类型的名称。//返回的字符串描述了用于存储数据的C++数据类型,const char * typeName() const;//如果变体类型可以转换为目标类型,则返回true。//在调用tolnt()、toBool() 方法时,会自动进行此类转换。bool canConvert(QMetaType targetType) const{ return QMetaType::canConvert(d.type(), targetType); }//将变体转换为请求的类型,type。//如果无法进行转换,则变体仍然会转换为请求的类型,但会变成空值,//类似于由 QVariant(Type)构造的状态。//如果变体类型的当前值已成功转换,则返回 true;否则返回 false。//包含指向从 QObject 派生的类型的指针的 QVariant,//如果对 type 描述的类型进行 qobject_cast成功,//则此函数也会转换并返回 true。请注意,//这仅适用于使用了 Q_OBJECT宏的 QOObiect 子类//注意:由于没有初始化或之前的转换失败了,//则这里的 OVariant转换也会失败为 null,将始终失败,//更改类型,保持 null,并返回 false。bool convert(QMetaType type); //注意形参为元类型bool canView(QMetaType targetType) const{ return QMetaType::canView(d.type(), targetType); }//Returns true if the storage type of this variant is not QMetaType::UnknownType;//  otherwise returns false.inline  bool isValid() const { return d.type().isValid(); }//Returns true if this is a null variant, false otherwise.//A variant is considered null if it contains no initialized value or a null pointer.bool isNull () const;inline  bool isDetached() const //无官方注释{ return !d.is_shared || d.data.shared->ref.loadRelaxed() == 1; }void detach(); //似乎是取消隐式共享的意思,为修改写入做准备//Convert this variant to type QMetaType::UnknownType and free up any resources used.void clear  (); //本函执行后对 isValid()返回 false,对 isNull () 返回true//Returns the variant as an int if the variant has QMetaType::Int()等,//otherwise returns 0.  转换失败则返回 0//If ok is non-null: * ok is set to true if the value could be converted to an int;//                          otherwise * ok is set to false.int        toInt      (bool * ok = nullptr) const;uint       toUInt     (bool * ok = nullptr) const;qlonglong  toLongLong (bool * ok = nullptr) const; //这些都类似,不再详细注释了qulonglong toULongLong(bool * ok = nullptr) const;double     toDouble   (bool * ok = nullptr) const;float      toFloat    (bool * ok = nullptr) const;qreal      toReal     (bool * ok = nullptr) const;bool       toBool     () const;QString     toString    () const;QChar       toChar      () const;QByteArray  toByteArray () const;QBitArray   toBitArray  () const;QStringList toStringList() const;QDate     toDate    () const;QTime     toTime    () const;QDateTime toDateTime() const;QList<QVariant>          toList() const; //QList<QVariant>QMap<QString , QVariant> toMap () const;QHash<QString, QVariant> toHash() const;//Returns the variant as a QUuid//if the variant has type() QMetaType::QUuid,//QMetaType::QByteArray or QMetaType::QString;//otherwise returns a default-constructed QUuid.QUuid   toUuid() const;//Returns the variant as a QLocale//if the variant has userType() QMetaType::QLocale;//otherwise returns an invalid QLocale.QLocale toLocale() const;#ifndef QT_NO_GEOM_VARIANT //看来是没定义,#if 有效QPoint  toPoint () const;QPointF toPointF() const;QRect   toRect  () const;QRectF  toRectF () const;QSize   toSize  () const;QSizeF  toSizeF () const;QLine   toLine  () const;QLineF  toLineF() const;
#endif //#ifndef QT_NO_GEOM_VARIANT#if QT_CONFIG(regularexpression) //正则表达式QRegularExpression toRegularExpression() const;
#endif // QT_CONFIG(regularexpression)#if QT_CONFIG(easingcurve) //缓动曲线QEasingCurve toEasingCurve() const;
#endif#ifndef QT_BOOTSTRAPPED  //此 if成立,面向 json 的,存在这些成员函数QUrl          toUrl         () const;QJsonValue    toJsonValue   () const;QJsonObject   toJsonObject  () const;QJsonArray    toJsonArray   () const;QJsonDocument toJsonDocument() const;
#endif // QT_BOOTSTRAPPED#if QT_CONFIG(itemmodel) //经测试是有这个宏定义的QModelIndex           toModelIndex          () const;QPersistentModelIndex toPersistentModelIndex() const;
#endif#ifndef QT_NO_DATASTREAMvoid load(QDataStream & ds);       //读void save(QDataStream & ds) const; //写
#endif#if QT_DEPRECATED_SINCE(6, 0) //里面的都是废弃的成员函数//.....全部删除了
#endif //#if QT_DEPRECATED_SINCE(6, 0)//template<typename T> //先来一个全局模板函数。函数声明//inline T qvariant_cast(const QVariant &);template<typename T> //注意,这是模板成员函数, T 可以为任何类型inline T value() const { return qvariant_cast<T>(*this); }void setValue(const QVariant &  avalue) { * this = avalue           ; }void setValue(      QVariant && avalue) { * this = std::move(avalue); }/*
template <bool _Test, class _Ty = void>
struct enable_if {}; // no member "type" when !_Testtemplate <class _Ty> // type is _Ty for _Test
struct enable_if<true, _Ty> { using type = _Ty; };template <bool _Test, class _Ty = void> //真才返回 T 或 void类型
using enable_if_t = typename enable_if<_Test, _Ty>::type;
//-----------------------------------------------------------------
template <class, class>
bool is_same_v = false;template <class _Ty>
bool is_same_v<_Ty, _Ty> = true;
*/template<typename T, typename = std::enable_if_t<!std::is_same_v< std::decay_t<T>, QVariant >>  >void setValue(T && avalue) //似乎是要求 T 不能为 QVariant类型{using VT = std::decay_t<T>;QMetaType metaType = QMetaType::fromType<VT>();// If possible we reuse the current QVariant private.if (isDetached() && d.type() == metaType) {*reinterpret_cast<VT *>(const_cast<void *>(constData()))= std::forward<T>(avalue);} else {*this = QVariant::fromValue<VT>(std::forward<T>(avalue));}}//Stores a copy of value.//If T is a type that QVariant doesn't support,//QMetaType is used to store the value.//A compile error will occur if QMetaType doesn't handle the type.//Returns a mutable view of template type T on the stored value.//Call canView() to find out whether such a view is supported.//If no such view can be created,//returns the stored value converted to the template type T.//Call canConvert() to find out whether a type can be converted.//If the value can neither be viewed nor converted,//a default-constructed value will be returned.template<typename T>inline T view(){   T t{};QMetaType::view(metaType(), data(), QMetaType::fromType<T>(), &t);return t;}//Returns true if T can be cast to the requested type, type.//Such casting is done automatically when calling the//  toInt(), toBool(), ... methods.template<typename T>bool canConvert() const{ return canConvert(QMetaType::fromType<T>()); }template<typename T>bool canView() const  //无官方注释{ return canView(QMetaType::fromType<T>()); }//返回值是本 QVariant 类型,本函数的意思是根据形参构造本类型。//Returns a QVariant containing a copy of value.//Behaves exactly like setValue() otherwise.template<typename T>static inline auto fromValue(const      T   & value)-> std::enable_if_t<std::is_copy_constructible_v<T>, QVariant>{return QVariant(QMetaType::fromType<T>(), std::addressof(value));}template<>inline   QVariant  fromValue(const QVariant & value) { return value; }template<>inline   QVariant  fromValue(const std::monostate &) { return QVariant(); }template<typename... Types>static inline QVariant fromStdVariant(const std::variant<Types...> & value){if (value.valueless_by_exception())return QVariant();return std::visit([](const auto &arg) { return fromValue(arg); }, value);}public://QPartialOrdering::Unordered//QPartialOrdering::Less//QPartialOrdering::Equivalent//QPartialOrdering::Greaterstatic QPartialOrdering compare(const QVariant & lhs, const QVariant & rhs);private: //定义了友元函数friend inline bool operator==(const QVariant & a, const QVariant & b){ return a.equals(b); }friend inline bool operator!=(const QVariant & a, const QVariant & b){ return !a.equals(b); }#ifndef QT_NO_DEBUG_STREAM //本函有效的template <typename T>  //即本变量可以被插入输入到 qDebug 里friend auto operator<<(const QDebug & debug, const T & variant)-> std::enable_if_t<std::is_same_v<T, QVariant>, QDebug>{return  variant.qdebugHelper(debug);}QDebug qdebugHelper(QDebug) const;
#endif//Returns the given value converted to the template type T.//This function is equivalent to QVariant::value().template<typename T>friend inline T qvariant_cast(const QVariant &);private: //一些私有成员函数// force compile error, prevent QVariant(bool) to be calledinline QVariant(void *) = delete; //不支持存储布尔型啊// QVariant::Type is marked as \obsolete,// but we don't want to provide a constructor from its intended replacement,// QMetaType::Type, instead,// because the idea behind these constructors// is flawed in the first place.// But we also don't want QVariant(QMetaType::String) to compile// and falsely be an int variant, so delete this constructor://QVariant::Type 被标记为 \obsolete,//但我们不想从其意图的替代者QMetaType::Type 中提供构造函数,//因为这些构造函数背后的想法从一开始就是有缺陷的。//但我们也不希望 QVariant(QMetaType::String)编译并错误地成为 int 变体,//因此删除这个构造函数:QVariant(QMetaType::Type) = delete;//These constructors don't create QVariants of the type associated with the enum,//as expected, but they would create// a QVariant of type int with the value of the enum value.// Use QVariant v = QColor(Qt::red) instead of QVariant v = Qt::red for example.//这些构造函数不会像预期的那样创建与枚举类型关联的 QVariants,//但它们会创建-个类型为 int的 OVariant,其值为枚举值。//例如,使用 QVariantv=QColor(Ot::red)而不是 OVariantv=Qt::red。QVariant(Qt::GlobalColor) = delete;QVariant(Qt::BrushStyle)  = delete;QVariant(Qt::PenStyle)    = delete;QVariant(Qt::CursorShape) = delete;#ifdef QT_NO_CAST_FROM_ASCII //经测试本宏是没有定义的// force compile error when implicit conversion is not wantedinline QVariant(const char *) = delete; //所以此函数是没有定义的
#endif}; //完结 class QVariant !!!!!!!!!
Q_DECLARE_SHARED(QVariant)namespace QtPrivate {
class Q_CORE_EXPORT QVariantTypeCoercer
{
public:const void *convert(const QVariant &value, const QMetaType &type);const void *coerce(const QVariant &value, const QMetaType &type);private:QVariant converted;
};
}template<typename Pointer>
class QVariantRef
{
private:const Pointer *m_pointer = nullptr;public:explicit QVariantRef(const Pointer *reference) : m_pointer(reference) {}QVariantRef(const QVariantRef &) = default;QVariantRef(QVariantRef &&) = default;~QVariantRef() = default;operator QVariant() const;QVariantRef &operator=(const QVariant &value);QVariantRef &operator=(const QVariantRef &value){ return operator=(QVariant(value)); }QVariantRef &operator=(QVariantRef &&value) { return operator=(QVariant(value)); }friend void swap(QVariantRef a, QVariantRef b){QVariant tmp = a;a = b;b = std::move(tmp);}
};class Q_CORE_EXPORT QVariantConstPointer
{
private:QVariant m_variant;public:explicit QVariantConstPointer(QVariant variant);QVariant operator*() const;const QVariant *operator->() const;
};template<typename Pointer>
class QVariantPointer
{
private:const Pointer *m_pointer = nullptr;public:explicit QVariantPointer(const Pointer *pointer) : m_pointer(pointer) {}QVariantRef<Pointer> operator*() const { return QVariantRef<Pointer>(m_pointer); }Pointer operator->() const { return *m_pointer; }
};QT_END_NAMESPACE#endif // QVARIANT_H

(11)

谢谢

相关文章:

  • 【计算机视觉】OpenCV实战项目:Text-Extraction-Table-Image:基于OpenCV与OCR的表格图像文本提取系统深度解析
  • 【愚公系列】《Manus极简入门》031-商业模式创新师:“模式筛选者”
  • MySQL数据库下篇
  • Python与矢量网络分析仪3671E:通道插损自动化校准(Vscode)
  • spring cloud loadbalancer实现机房感知的负载均衡
  • CSS:盒子阴影与渐变完全解析:从基础语法到创意应用
  • 大模型中的temperature参数是什么
  • LLMs之MCP:2025年5月2日,Anthropic 宣布 Claude 重大更新:集成功能上线,研究能力大幅提升
  • React+Springboot项目部署ESC服务器
  • 大学之大:东京工业大学2025.5.11
  • Pandas 时间处理利器:to_datetime() 与 Timestamp() 深度解析
  • 17.【.NET 8 实战--孢子记账--从单体到微服务--转向微服务】--微服务基础工具与技术--loki
  • web animation API 锋利的css动画控制器 (更新中)
  • 基于神经网络的无源雷达测向系统仿真实现
  • 深入浅出之STL源码分析2_stl与标准库,编译器的关系
  • 保姆级教程|YOLO11改进】【卷积篇】【4】使用RFAConv感受野注意力卷积,重塑空间特征提取,助力高效提点
  • 《AI大模型应知应会100篇》第58篇:Semantic Kernel:微软的大模型应用框架
  • 【Bootstrap V4系列】学习入门教程之 组件-媒体对象(Media object)
  • Java 原生异步编程与Spring 异步编程 详解
  • 生产级 Flink CDC 应用开发与部署:MySQL 到 Kafka 同步示例
  • 长沙通报一出租房疑存非法代孕:查封涉事场所,相关人员被控制
  • 黑灰产工作室为境外诈骗集团养号引流,冒充美女与男性裸聊后敲诈勒索
  • 明查|哈佛大学批改美教育部长来信,红笔标出语法错误?
  • 甘肃省政府原副省长赵金云被决定逮捕
  • 央行:全力推进一揽子金融政策加快落地
  • 债券市场“科技板”来了:哪些机构能尝鲜,重点支持哪些领域