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

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)

谢谢

相关文章:

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

&#xff08;9&#xff09; 本类支持比较运算符 、! &#xff1a; 可见&#xff0c; QString 类型里可存储多个 unicode 字符&#xff0c;即使只存储一个 unicode 字符也不等于 QChar。 &#xff08;10&#xff09;本源代码来自于头文件 qvariant . h &#xff1a; #ifndef Q…...

Maven私服搭建与登录全攻略

目录 1.背景2.简介3.安装4.启动总结参考文献 1.背景 回顾下maven的构建流程&#xff0c;如果没有私服&#xff0c;我们所需的所有jar包都需要通过maven的中央仓库或者第三方的maven仓库下载到本地&#xff0c;当一个公司或者一个团队所有人都重复的从maven仓库下载jar包&#…...

力扣210(拓扑排序)

210. 课程表 II - 力扣&#xff08;LeetCode&#xff09; 这是一道拓扑排序的模板题。简单来说&#xff0c;给出一个有向图&#xff0c;把这个有向图转成线性的排序就叫拓扑排序。如果有向图中有环就没有办法进行拓扑排序了。因此&#xff0c;拓扑排序也是图论中判断有向无环图…...

1.1 文章简介

前因后果链 行业需求 → 技能断层 → 课程设计响应 (高薪岗位要求数学基础) → (符号/公式理解困难) → (聚焦原理与应用) 行业驱动因素 • 前因&#xff1a;机器学习/AI等领域的高薪岗位激增&#xff0c;但数学能力成为主要门槛 • 关键矛盾&#xff1a;算法论文中的数学…...

将本地文件上传到云服务器上

使用 SCP 命令&#xff08;最常用&#xff09; # 基本语法 scp [本地文件路径] [用户名][服务器IP]:[目标路径]# 示例&#xff1a;上传单个文件 scp /path/to/local/file.txt root192.168.1.100:/path/to/remote/# 上传整个目录 scp -r /path/to/local/directory root192.168.…...

C++ asio网络编程(5)简单异步echo服务器

上一篇文章:C asio网络编程(4)异步读写操作及注意事项 文章目录 前言一、Session类1.代码2.代码详解3.实现Session类1.构造函数2.handle_read3.介绍一下boost的封装函数和api4.handle_write 二、Server类1.代码2.代码思路详解 三、客户端四、运行截图与流程图 前言 提示&…...

【机器人】复现 UniGoal 具身导航 | 通用零样本目标导航 CVPR 2025

UniGoal的提出了一个通用的零样本目标导航框架&#xff0c;能够统一处理多种类型的导航任务。 支持 对象类别导航、实例图像目标导航和文本目标导航&#xff0c;而无需针对特定任务进行训练或微调。 本文分享UniGoal复现和模型推理的过程&#xff5e; 查找沙发&#xff0c;模…...

基于大模型预测的吉兰 - 巴雷综合征综合诊疗方案研究报告大纲

目录 一、引言(一)研究背景(二)研究目的与意义二、大模型预测吉兰 - 巴雷综合征的理论基础与技术架构(一)大模型原理概述(二)技术架构设计三、术前预测与手术方案制定(一)术前预测内容(二)手术方案制定依据与策略四、术中监测与麻醉方案调整(一)术中监测指标与数…...

spring中的@PropertySource注解详解

一、核心功能与作用 PropertySource是Spring框架中用于加载外部配置文件的核心注解&#xff0c;主要作用是将属性文件&#xff08;如.properties、.yml&#xff09;的键值对加载到Spring的Environment环境中&#xff0c;实现配置与代码的解耦。其核心价值包括&#xff1a; 外部…...

ChromeDriver 技术生态与应用场景深度解析

ChromeDriver 技术生态与应用场景深度解析 随着 Web 自动化测试、运维和数据采集需求的不断增长&#xff0c;ChromeDriver 及其相关技术栈在各行业中扮演着举足轻重的角色。本文将从技术选型、语言适配、典型场景、技术延伸等维度&#xff0c;结合最新行业趋势与实践经验&…...

【NextPilot日志移植】日志写入流程

&#x1f4dd; 文件后端日志写入流程详解 当后端选择文件时&#xff0c;日志写入过程主要涉及 LogWriter 和 LogWriterFile 类的协作。以下是详细的日志写入过程解释及涉及的代码&#xff1a; 1. LogWriter 类初始化 在 LogWriter 类的构造函数中&#xff0c;如果配置的后端…...

二极管钳位电路——Multisim电路仿真

目录 二极管钳位电路 2.1 二极管正向钳位电路 二极管压降测试 2.1.1 二极管正向钳位电路图 2.1.2 二极管正向钳位工作原理 2.2 二极管负向钳位电路 2.2.1 二极管负向钳位电路图 2.2.2 二极管负向钳位工作原理 二极管正向反向钳位仿真电路实验结果 2.3 二极管顶部钳位…...

Docker编排工具---Compose的概述及使用

目录 一、Compose工具的概述 二、Compose的常用命令 1、列出容器 2、查看访问日志 3、输出绑定的公共端口 4、重新构建服务 5、启动服务 6、停止服务 7、删除已停止服务的容器 8、创建和启动容器 9、在运行的容器中执行命令 10、指定一个服务启动容器的个数 11、其…...

5.10-套接字通信 - C++

套接字通信 1.1 通信效率问题 服务器端 单线程 / 单进程 无法使用&#xff0c;不支持多客户端 多线程 / 多进程 写程序优先考虑多线程&#xff1a;什么时候考虑多进程&#xff1f; 启动了一个可执行程序 A &#xff0c;要在 A 中启动一个可执行程序 B 支持多客户端连接 IO 多…...

suricata增加单元测试编译失败

一、环境 $ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 22.04.5 LTS Release: 22.04 Codename: jammysuricata: suricata7.0.5 IDE: vscode 二、背景 在suricata中开发了某个功能后&#xff0c;增加unittest时&#xff0c;…...

高并发场景下的BI架构设计:衡石分布式查询引擎与缓存分级策略

在电商大促、金融交易时段或IoT实时监控场景中&#xff0c;企业BI系统常面临瞬时万级并发查询的冲击——运营团队需要实时追踪GMV波动&#xff0c;风控部门需秒级响应欺诈检测&#xff0c;产线监控需毫秒级反馈设备状态。传统单体架构的BI系统在此类场景下极易崩溃&#xff0c;…...

鱼眼摄像头(一)多平面格式 单缓冲读取图像并显示

鱼眼摄像头&#xff08;一&#xff09;多平面格式 单缓冲读取图像并显示 1.摄像头格式 1. 单平面格式&#xff08;Single Plane&#xff09;&#xff1a;各通道数据保存在同一个平面&#xff08;缓冲&#xff09;&#xff0c;图像数据按行连续存储a. mjpeg&#xff0c;yuyv等…...

机器学习笔记——特征工程

大家好&#xff0c;这里是好评笔记&#xff0c;公主号&#xff1a;Goodnote&#xff0c;专栏文章私信限时Free。本笔记介绍机器学习中常见的特征工程方法、正则化方法和简要介绍强化学习。 文章目录 特征工程&#xff08;Fzeature Engineering&#xff09;1. 特征提取&#xff…...

A Survey of Learning from Rewards:从训练到应用的全面剖析

A Survey of Learning from Rewards&#xff1a;从训练到应用的全面剖析 你知道大语言模型&#xff08;LLMs&#xff09;如何通过奖励学习变得更智能吗&#xff1f;这篇论文将带你深入探索。从克服预训练局限的新范式&#xff0c;到训练、推理各阶段的策略&#xff0c;再到广泛…...

Python爬虫第20节-使用 Selenium 爬取小米商城空调商品

目录 前言 一、 本文目标 二、环境准备 2.1 安装依赖 2.2 配置 ChromeDriver 三、小米商城页面结构分析 3.1 商品列表结构 3.2 分页结构 四、Selenium 自动化爬虫实现 4.1 脚本整体结构 4.2 代码实现 五、关键技术详解 5.1 Selenium 启动与配置 5.2 页面等待与异…...

无线定位之 三 SX1302 网关源码 thread_gps 线程详解

前言 笔者计划通过无线定位系列文章、系统的描述 TDOA 无线定位和混合定位相关技术知识点, 并以实践来验证此定位系统精度。 笔者从实践出发、本篇直接走读无线定位系统关键节点、网关 SX1302 源码框架,并在源码走读过程 中、着重分析与无线定位相关的PPS时间的来龙去脉、并在…...

Aware和InitializingBean接口以及@Autowired注解失效分析

Aware 接口用于注入一些与容器相关信息&#xff0c;例如&#xff1a; ​ a. BeanNameAware 注入 Bean 的名字 ​ b. BeanFactoryAware 注入 BeanFactory 容器 ​ c. ApplicationContextAware 注入 ApplicationContext 容器 ​ d. EmbeddedValueResolverAware 注入 解析器&a…...

Unity3D仿星露谷物语开发41之创建池管理器

1、目标 在PersistentScene中创建池管理器&#xff08;Pool Manager&#xff09;。这将允许一个预制对象池被创建和重用。 在游戏中当鼠标点击地面时&#xff0c;便会启用某一个对象。比如点击地面&#xff0c;就创建了一棵树&#xff0c;而这棵树是从预制体对象池中获取的&a…...

Modbus协议介绍

Modbus是一种串行通信协议&#xff0c;由Modicon公司&#xff08;现为施耐德电气&#xff09;在1979年为可编程逻辑控制器&#xff08;PLC&#xff09;通信而开发。它是工业自动化领域最常用的通信协议之一&#xff0c;具有开放性、简单性和跨平台兼容性&#xff0c;广泛应用于…...

深度学习遇到的问题处理

小土堆课程学习 1.tensorboard远程到本地无法显示 1.检查本地与远程端口是否被占用 2.一定要在远程服务器的项目下创建对应的存储文件夹 且 远程服务器一定要有需要处理的数据 ## 此时远程项目路径下有logs文件夹 存放上传的图像与数据 writerSummaryWriter("logs"…...

I/O多路复用(select/poll/epoll)

通过一个进程来维护多个Socket&#xff0c;也就是I/O多路复用&#xff0c;是一种常见的并发编程技术&#xff0c;它允许单个线程或进程同时监视多个输入/输出&#xff08;I/O&#xff09;流&#xff08;例如网络连接、文件描述符&#xff09;。当任何一个I/O流准备好进行读写操…...

Westlake-Omni 情感端音频生成式输出模型

简述 github地址在 GitHub - xinchen-ai/Westlake-OmniContribute to xinchen-ai/Westlake-Omni development by creating an account on GitHub.https://github.com/xinchen-ai/Westlake-Omni Westlake-Omni 是由西湖心辰&#xff08;xinchen-ai&#xff09;开发的一个开源…...

Egg.js知识框架

一、Egg.js 核心概念 1. Egg.js 简介 基于 Koa 的企业级 Node.js 框架&#xff08;阿里开源&#xff09; 约定优于配置&#xff08;Convention over Configuration&#xff09; 插件化架构&#xff0c;内置多进程管理、日志、安全等能力 适合中大型企业应用&#xff0c;提供…...

随手记录5

一些顶级思维&#xff1a; ​ 顶级思维 1、永远不要自卑。 也永远不要感觉自己比别人差&#xff0c;这个人有没有钱&#xff0c;有多少钱&#xff0c;其实跟你都没有关系。有很多人就是那个奴性太强&#xff0c;看到比自己优秀的人&#xff0c;甚至一些装逼的人&#xff0c;这…...

Linux驱动:驱动编译流程了解

要求 1、开发板中的linux的zImage必须是自己编译的 2、内核源码树,其实就是一个经过了配置编译之后的内核源码。 3、nfs挂载的rootfs,主机ubuntu中必须搭建一个nfs服务器。 内核源码树 解压 tar -jxvf x210kernel.tar.bz2 编译 make x210ii_qt_defconfigmakeCan’t use ‘…...