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

发布于:2025-05-12 ⋅ 阅读:(15) ⋅ 点赞:(0)

(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; }
#endif

QT_BEGIN_NAMESPACE


class QBitArray;
class QDataStream;
class QDate;
class QDateTime;

#if QT_CONFIG(easingcurve)
    class QEasingCurve;
#endif

class 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);
#endif

template<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 QVariant
        QT_FOR_EACH_STATIC_TYPE(QT_DEFINE_METATYPE_ID)

        FirstCoreType     = Bool,         //=  1
         LastCoreType     = QVariantPair, //= 58

        FirstGuiType      = QFont,       //=0x1000
         LastGuiType      = QColorSpace, //=0x1017

        FirstWidgetsType  = QSizePolicy, //=0x2000
         LastWidgetsType  = QSizePolicy, //=0x2000

        HighestInternalId = LastWidgetsType, //=0x2000

        QReal = 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::PrivateShared
            ps->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 PrivateShared

    struct 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 类型的数据成员,名字叫 data

        quintptr 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 time
        template<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 Private

protected :
    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) //缓和曲线 easingcurve
    QVariant(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_DATASTREAM
    void 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 !_Test

template <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::Greater
    static 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 called
    inline 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 wanted
    inline 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)

谢谢


网站公告

今日签到

点亮在社区的每一天
去签到