/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QVARIANT_H #define QVARIANT_H #include #include #include #include #include #include #include #include #include #ifndef QT_BOOTSTRAPPED #include #endif QT_BEGIN_NAMESPACE class QBitArray; class QDataStream; class QDate; class QDateTime; class QEasingCurve; class QLine; class QLineF; class QLocale; class QMatrix; class QTransform; class QStringList; class QTime; class QPoint; class QPointF; class QSize; class QSizeF; class QRect; class QRectF; #ifndef QT_NO_REGEXP class QRegExp; #endif // QT_NO_REGEXP #ifndef QT_NO_REGULAREXPRESSION class QRegularExpression; #endif // QT_NO_REGULAREXPRESSION class QTextFormat; class QTextLength; class QUrl; class QVariant; class QVariantComparisonHelper; template inline QVariant qVariantFromValue(const T &); template inline T qvariant_cast(const QVariant &); namespace QtPrivate { template struct ObjectInvoker { static ReturnType invoke(Argument a) { return Derived::object(a); } }; template struct MetaTypeInvoker { static ReturnType invoke(Argument a) { return Derived::metaType(a); } }; template ::Value> struct TreatAsQObjectBeforeMetaType : ObjectInvoker { }; template struct TreatAsQObjectBeforeMetaType : MetaTypeInvoker { }; template struct QVariantValueHelper; } class Q_CORE_EXPORT QVariant { public: enum Type { Invalid = QMetaType::UnknownType, Bool = QMetaType::Bool, Int = QMetaType::Int, UInt = QMetaType::UInt, LongLong = QMetaType::LongLong, ULongLong = QMetaType::ULongLong, Double = QMetaType::Double, Char = QMetaType::QChar, Map = QMetaType::QVariantMap, List = QMetaType::QVariantList, String = QMetaType::QString, StringList = QMetaType::QStringList, ByteArray = QMetaType::QByteArray, BitArray = QMetaType::QBitArray, Date = QMetaType::QDate, Time = QMetaType::QTime, DateTime = QMetaType::QDateTime, Url = QMetaType::QUrl, Locale = QMetaType::QLocale, Rect = QMetaType::QRect, RectF = QMetaType::QRectF, Size = QMetaType::QSize, SizeF = QMetaType::QSizeF, Line = QMetaType::QLine, LineF = QMetaType::QLineF, Point = QMetaType::QPoint, PointF = QMetaType::QPointF, RegExp = QMetaType::QRegExp, RegularExpression = QMetaType::QRegularExpression, Hash = QMetaType::QVariantHash, EasingCurve = QMetaType::QEasingCurve, Uuid = QMetaType::QUuid, ModelIndex = QMetaType::QModelIndex, PersistentModelIndex = QMetaType::QPersistentModelIndex, LastCoreType = QMetaType::LastCoreType, Font = QMetaType::QFont, Pixmap = QMetaType::QPixmap, Brush = QMetaType::QBrush, Color = QMetaType::QColor, Palette = QMetaType::QPalette, Image = QMetaType::QImage, Polygon = QMetaType::QPolygon, Region = QMetaType::QRegion, Bitmap = QMetaType::QBitmap, Cursor = QMetaType::QCursor, KeySequence = QMetaType::QKeySequence, Pen = QMetaType::QPen, TextLength = QMetaType::QTextLength, TextFormat = QMetaType::QTextFormat, Matrix = QMetaType::QMatrix, Transform = QMetaType::QTransform, Matrix4x4 = QMetaType::QMatrix4x4, Vector2D = QMetaType::QVector2D, Vector3D = QMetaType::QVector3D, Vector4D = QMetaType::QVector4D, Quaternion = QMetaType::QQuaternion, PolygonF = QMetaType::QPolygonF, Icon = QMetaType::QIcon, LastGuiType = QMetaType::LastGuiType, SizePolicy = QMetaType::QSizePolicy, UserType = QMetaType::User, LastType = 0xffffffff // need this so that gcc >= 3.4 allocates 32 bits for Type }; QVariant() Q_DECL_NOTHROW : d() {} ~QVariant(); QVariant(Type type); QVariant(int typeId, const void *copy); QVariant(int typeId, const void *copy, uint flags); QVariant(const QVariant &other); #ifndef QT_NO_DATASTREAM QVariant(QDataStream &s); #endif QVariant(int i); QVariant(uint ui); QVariant(qlonglong ll); QVariant(qulonglong ull); QVariant(bool b); QVariant(double d); QVariant(float f); #ifndef QT_NO_CAST_FROM_ASCII QT_ASCII_CAST_WARN QVariant(const char *str); #endif QVariant(const QByteArray &bytearray); QVariant(const QBitArray &bitarray); QVariant(const QString &string); QVariant(QLatin1String string); QVariant(const QStringList &stringlist); QVariant(QChar qchar); QVariant(const QDate &date); QVariant(const QTime &time); QVariant(const QDateTime &datetime); QVariant(const QList &list); QVariant(const QMap &map); QVariant(const QHash &hash); #ifndef QT_NO_GEOM_VARIANT QVariant(const QSize &size); QVariant(const QSizeF &size); QVariant(const QPoint &pt); QVariant(const QPointF &pt); QVariant(const QLine &line); QVariant(const QLineF &line); QVariant(const QRect &rect); QVariant(const QRectF &rect); #endif QVariant(const QLocale &locale); #ifndef QT_NO_REGEXP QVariant(const QRegExp ®Exp); #endif // QT_NO_REGEXP #ifndef QT_BOOTSTRAPPED #ifndef QT_NO_REGULAREXPRESSION QVariant(const QRegularExpression &re); #endif // QT_NO_REGULAREXPRESSION QVariant(const QUrl &url); QVariant(const QEasingCurve &easing); QVariant(const QUuid &uuid); QVariant(const QModelIndex &modelIndex); QVariant(const QPersistentModelIndex &modelIndex); QVariant(const QJsonValue &jsonValue); QVariant(const QJsonObject &jsonObject); QVariant(const QJsonArray &jsonArray); QVariant(const QJsonDocument &jsonDocument); #endif // QT_BOOTSTRAPPED QVariant& operator=(const QVariant &other); #ifdef Q_COMPILER_RVALUE_REFS inline QVariant(QVariant &&other) Q_DECL_NOTHROW : d(other.d) { other.d = Private(); } inline QVariant &operator=(QVariant &&other) Q_DECL_NOTHROW { qSwap(d, other.d); return *this; } #endif inline void swap(QVariant &other) Q_DECL_NOTHROW { qSwap(d, other.d); } Type type() const; int userType() const; const char *typeName() const; bool canConvert(int targetTypeId) const; bool convert(int targetTypeId); inline bool isValid() const; bool isNull() const; void clear(); void detach(); inline bool isDetached() const; int toInt(bool *ok = Q_NULLPTR) const; uint toUInt(bool *ok = Q_NULLPTR) const; qlonglong toLongLong(bool *ok = Q_NULLPTR) const; qulonglong toULongLong(bool *ok = Q_NULLPTR) const; bool toBool() const; double toDouble(bool *ok = Q_NULLPTR) const; float toFloat(bool *ok = Q_NULLPTR) const; qreal toReal(bool *ok = Q_NULLPTR) const; QByteArray toByteArray() const; QBitArray toBitArray() const; QString toString() const; QStringList toStringList() const; QChar toChar() const; QDate toDate() const; QTime toTime() const; QDateTime toDateTime() const; QList toList() const; QMap toMap() const; QHash toHash() const; #ifndef QT_NO_GEOM_VARIANT QPoint toPoint() const; QPointF toPointF() const; QRect toRect() const; QSize toSize() const; QSizeF toSizeF() const; QLine toLine() const; QLineF toLineF() const; QRectF toRectF() const; #endif QLocale toLocale() const; #ifndef QT_NO_REGEXP QRegExp toRegExp() const; #endif // QT_NO_REGEXP #ifndef QT_BOOTSTRAPPED #ifndef QT_NO_REGULAREXPRESSION QRegularExpression toRegularExpression() const; #endif // QT_NO_REGULAREXPRESSION QUrl toUrl() const; QEasingCurve toEasingCurve() const; QUuid toUuid() const; QModelIndex toModelIndex() const; QPersistentModelIndex toPersistentModelIndex() const; QJsonValue toJsonValue() const; QJsonObject toJsonObject() const; QJsonArray toJsonArray() const; QJsonDocument toJsonDocument() const; #endif // QT_BOOTSTRAPPED #ifndef QT_NO_DATASTREAM void load(QDataStream &ds); void save(QDataStream &ds) const; #endif static const char *typeToName(int typeId); static Type nameToType(const char *name); void *data(); const void *constData() const; inline const void *data() const { return constData(); } template inline void setValue(const T &value); template inline T value() const { return qvariant_cast(*this); } template static inline QVariant fromValue(const T &value) { return qVariantFromValue(value); } template bool canConvert() const { return canConvert(qMetaTypeId()); } public: #ifndef Q_QDOC struct PrivateShared { inline PrivateShared(void *v) : ptr(v), ref(1) { } void *ptr; QAtomicInt ref; }; struct Private { inline Private() Q_DECL_NOTHROW : type(Invalid), is_shared(false), is_null(true) { data.ptr = Q_NULLPTR; } // Internal constructor for initialized variants. explicit inline Private(uint variantType) Q_DECL_NOTHROW : type(variantType), is_shared(false), is_null(false) {} inline Private(const Private &other) Q_DECL_NOTHROW : data(other.data), type(other.type), is_shared(other.is_shared), is_null(other.is_null) {} union Data { char c; uchar uc; short s; signed char sc; ushort us; int i; uint u; long l; ulong ul; bool b; double d; float f; qreal real; qlonglong ll; qulonglong ull; QObject *o; void *ptr; PrivateShared *shared; } data; uint type : 30; uint is_shared : 1; uint is_null : 1; }; public: typedef void (*f_construct)(Private *, const void *); typedef void (*f_clear)(Private *); typedef bool (*f_null)(const Private *); #ifndef QT_NO_DATASTREAM typedef void (*f_load)(Private *, QDataStream &); typedef void (*f_save)(const Private *, QDataStream &); #endif typedef bool (*f_compare)(const Private *, const Private *); typedef bool (*f_convert)(const QVariant::Private *d, int t, void *, bool *); typedef bool (*f_canConvert)(const QVariant::Private *d, int t); typedef void (*f_debugStream)(QDebug, const QVariant &); struct Handler { f_construct construct; f_clear clear; f_null isNull; #ifndef QT_NO_DATASTREAM f_load load; f_save save; #endif f_compare compare; f_convert convert; f_canConvert canConvert; f_debugStream debugStream; }; #endif inline bool operator==(const QVariant &v) const { return cmp(v); } inline bool operator!=(const QVariant &v) const { return !cmp(v); } inline bool operator<(const QVariant &v) const { return compare(v) < 0; } inline bool operator<=(const QVariant &v) const { return compare(v) <= 0; } inline bool operator>(const QVariant &v) const { return compare(v) > 0; } inline bool operator>=(const QVariant &v) const { return compare(v) >= 0; } protected: friend inline bool operator==(const QVariant &, const QVariantComparisonHelper &); #ifndef QT_NO_DEBUG_STREAM friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QVariant &); #endif // ### Qt6: FIXME: Remove the special Q_CC_MSVC handling, it was introduced to maintain BC for QTBUG-41810 . #if !defined(Q_NO_TEMPLATE_FRIENDS) && !defined(Q_CC_MSVC) template friend inline T qvariant_cast(const QVariant &); template friend struct QtPrivate::QVariantValueHelper; protected: #else public: #endif Private d; void create(int type, const void *copy); bool cmp(const QVariant &other) const; int compare(const QVariant &other) const; bool convert(const int t, void *ptr) const; private: // force compile error, prevent QVariant(bool) to be called inline QVariant(void *) Q_DECL_EQ_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(QMetaType::Type) Q_DECL_EQ_DELETE; // These constructors don't create QVariants of the type associcated // 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. QVariant(Qt::GlobalColor) Q_DECL_EQ_DELETE; QVariant(Qt::BrushStyle) Q_DECL_EQ_DELETE; QVariant(Qt::PenStyle) Q_DECL_EQ_DELETE; QVariant(Qt::CursorShape) Q_DECL_EQ_DELETE; #ifdef QT_NO_CAST_FROM_ASCII // force compile error when implicit conversion is not wanted inline QVariant(const char *) Q_DECL_EQ_DELETE; #endif public: typedef Private DataPtr; inline DataPtr &data_ptr() { return d; } inline const DataPtr &data_ptr() const { return d; } }; template inline QVariant qVariantFromValue(const T &t) { return QVariant(qMetaTypeId(), &t, QTypeInfo::isPointer); } template <> inline QVariant qVariantFromValue(const QVariant &t) { return t; } template inline void qVariantSetValue(QVariant &v, const T &t) { //if possible we reuse the current QVariant private const uint type = qMetaTypeId(); QVariant::Private &d = v.data_ptr(); if (v.isDetached() && (type == d.type || (type <= uint(QVariant::Char) && d.type <= uint(QVariant::Char)))) { d.type = type; d.is_null = false; T *old = reinterpret_cast(d.is_shared ? d.data.shared->ptr : &d.data.ptr); if (QTypeInfo::isComplex) old->~T(); new (old) T(t); //call the copy constructor } else { v = QVariant(type, &t, QTypeInfo::isPointer); } } template <> inline void qVariantSetValue(QVariant &v, const QVariant &t) { v = t; } inline bool QVariant::isValid() const { return d.type != Invalid; } template inline void QVariant::setValue(const T &avalue) { qVariantSetValue(*this, avalue); } #ifndef QT_NO_DATASTREAM Q_CORE_EXPORT QDataStream& operator>> (QDataStream& s, QVariant& p); Q_CORE_EXPORT QDataStream& operator<< (QDataStream& s, const QVariant& p); Q_CORE_EXPORT QDataStream& operator>> (QDataStream& s, QVariant::Type& p); Q_CORE_EXPORT QDataStream& operator<< (QDataStream& s, const QVariant::Type p); #endif inline bool QVariant::isDetached() const { return !d.is_shared || d.data.shared->ref.load() == 1; } #ifdef Q_QDOC inline bool operator==(const QVariant &v1, const QVariant &v2); inline bool operator!=(const QVariant &v1, const QVariant &v2); #else /* Helper class to add one more level of indirection to prevent implicit casts. */ class QVariantComparisonHelper { public: inline QVariantComparisonHelper(const QVariant &var) : v(&var) {} private: friend inline bool operator==(const QVariant &, const QVariantComparisonHelper &); const QVariant *v; }; inline bool operator==(const QVariant &v1, const QVariantComparisonHelper &v2) { return v1.cmp(*v2.v); } inline bool operator!=(const QVariant &v1, const QVariantComparisonHelper &v2) { return !operator==(v1, v2); } #endif Q_DECLARE_SHARED(QVariant) class Q_CORE_EXPORT QSequentialIterable { QtMetaTypePrivate::QSequentialIterableImpl m_impl; public: struct Q_CORE_EXPORT const_iterator { private: QtMetaTypePrivate::QSequentialIterableImpl m_impl; QAtomicInt *ref; friend class QSequentialIterable; explicit const_iterator(const QSequentialIterable &iter, QAtomicInt *ref_); explicit const_iterator(const QtMetaTypePrivate::QSequentialIterableImpl &impl, QAtomicInt *ref_); void begin(); void end(); public: ~const_iterator(); const_iterator(const const_iterator &other); const_iterator& operator=(const const_iterator &other); const QVariant operator*() const; bool operator==(const const_iterator &o) const; bool operator!=(const const_iterator &o) const; const_iterator &operator++(); const_iterator operator++(int); const_iterator &operator--(); const_iterator operator--(int); const_iterator &operator+=(int j); const_iterator &operator-=(int j); const_iterator operator+(int j) const; const_iterator operator-(int j) const; }; friend struct const_iterator; #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) explicit QSequentialIterable(QtMetaTypePrivate::QSequentialIterableImpl impl); #else explicit QSequentialIterable(const QtMetaTypePrivate::QSequentialIterableImpl &impl); #endif const_iterator begin() const; const_iterator end() const; QVariant at(int idx) const; int size() const; bool canReverseIterate() const; }; class Q_CORE_EXPORT QAssociativeIterable { QtMetaTypePrivate::QAssociativeIterableImpl m_impl; public: struct Q_CORE_EXPORT const_iterator { private: QtMetaTypePrivate::QAssociativeIterableImpl m_impl; QAtomicInt *ref; friend class QAssociativeIterable; explicit const_iterator(const QAssociativeIterable &iter, QAtomicInt *ref_); explicit const_iterator(const QtMetaTypePrivate::QAssociativeIterableImpl &impl, QAtomicInt *ref_); void begin(); void end(); void find(const QVariant &key); public: ~const_iterator(); const_iterator(const const_iterator &other); const_iterator& operator=(const const_iterator &other); const QVariant key() const; const QVariant value() const; const QVariant operator*() const; bool operator==(const const_iterator &o) const; bool operator!=(const const_iterator &o) const; const_iterator &operator++(); const_iterator operator++(int); const_iterator &operator--(); const_iterator operator--(int); const_iterator &operator+=(int j); const_iterator &operator-=(int j); const_iterator operator+(int j) const; const_iterator operator-(int j) const; }; friend struct const_iterator; #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) explicit QAssociativeIterable(QtMetaTypePrivate::QAssociativeIterableImpl impl); #else explicit QAssociativeIterable(const QtMetaTypePrivate::QAssociativeIterableImpl &impl); #endif const_iterator begin() const; const_iterator end() const; const_iterator find(const QVariant &key) const; QVariant value(const QVariant &key) const; int size() const; }; #ifndef QT_MOC namespace QtPrivate { template struct QVariantValueHelper : TreatAsQObjectBeforeMetaType, T, const QVariant &, T> { static T metaType(const QVariant &v) { const int vid = qMetaTypeId(); if (vid == v.userType()) return *reinterpret_cast(v.constData()); T t; if (v.convert(vid, &t)) return t; return T(); } #ifndef QT_NO_QOBJECT static T object(const QVariant &v) { return qobject_cast(QMetaType::typeFlags(v.userType()) & QMetaType::PointerToQObject ? v.d.data.o : QVariantValueHelper::metaType(v)); } #endif }; template struct QVariantValueHelperInterface : QVariantValueHelper { }; template<> struct QVariantValueHelperInterface { static QSequentialIterable invoke(const QVariant &v) { const int typeId = v.userType(); if (typeId == qMetaTypeId()) { return QSequentialIterable(QtMetaTypePrivate::QSequentialIterableImpl(reinterpret_cast(v.constData()))); } if (typeId == qMetaTypeId()) { return QSequentialIterable(QtMetaTypePrivate::QSequentialIterableImpl(reinterpret_cast(v.constData()))); } #ifndef QT_BOOTSTRAPPED if (typeId == qMetaTypeId()) { return QSequentialIterable(QtMetaTypePrivate::QSequentialIterableImpl(reinterpret_cast(v.constData()))); } #endif return QSequentialIterable(v.value()); } }; template<> struct QVariantValueHelperInterface { static QAssociativeIterable invoke(const QVariant &v) { const int typeId = v.userType(); if (typeId == qMetaTypeId()) { return QAssociativeIterable(QtMetaTypePrivate::QAssociativeIterableImpl(reinterpret_cast(v.constData()))); } if (typeId == qMetaTypeId()) { return QAssociativeIterable(QtMetaTypePrivate::QAssociativeIterableImpl(reinterpret_cast(v.constData()))); } return QAssociativeIterable(v.value()); } }; template<> struct QVariantValueHelperInterface { static QVariantList invoke(const QVariant &v) { const int typeId = v.userType(); if (typeId == qMetaTypeId() || typeId == qMetaTypeId() || QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId())) { QSequentialIterable iter = QVariantValueHelperInterface::invoke(v); QVariantList l; l.reserve(iter.size()); for (QSequentialIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it) l << *it; return l; } return QVariantValueHelper::invoke(v); } }; template<> struct QVariantValueHelperInterface { static QVariantHash invoke(const QVariant &v) { const int typeId = v.userType(); if (typeId == qMetaTypeId() || QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId())) { QAssociativeIterable iter = QVariantValueHelperInterface::invoke(v); QVariantHash l; l.reserve(iter.size()); for (QAssociativeIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it) l.insertMulti(it.key().toString(), it.value()); return l; } return QVariantValueHelper::invoke(v); } }; template<> struct QVariantValueHelperInterface { static QVariantMap invoke(const QVariant &v) { const int typeId = v.userType(); if (typeId == qMetaTypeId() || QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId())) { QAssociativeIterable iter = QVariantValueHelperInterface::invoke(v); QVariantMap l; for (QAssociativeIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it) l.insertMulti(it.key().toString(), it.value()); return l; } return QVariantValueHelper::invoke(v); } }; template<> struct QVariantValueHelperInterface > { static QPair invoke(const QVariant &v) { const int typeId = v.userType(); if (typeId == qMetaTypeId >()) return QVariantValueHelper >::invoke(v); if (QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId())) { QtMetaTypePrivate::QPairVariantInterfaceImpl pi = v.value(); const QtMetaTypePrivate::VariantData d1 = pi.first(); QVariant v1(d1.metaTypeId, d1.data, d1.flags); if (d1.metaTypeId == qMetaTypeId()) v1 = *reinterpret_cast(d1.data); const QtMetaTypePrivate::VariantData d2 = pi.second(); QVariant v2(d2.metaTypeId, d2.data, d2.flags); if (d2.metaTypeId == qMetaTypeId()) v2 = *reinterpret_cast(d2.data); return QPair(v1, v2); } return QVariantValueHelper >::invoke(v); } }; } template inline T qvariant_cast(const QVariant &v) { return QtPrivate::QVariantValueHelperInterface::invoke(v); } template<> inline QVariant qvariant_cast(const QVariant &v) { if (v.userType() == QMetaType::QVariant) return *reinterpret_cast(v.constData()); return v; } #if QT_DEPRECATED_SINCE(5, 0) template inline QT_DEPRECATED T qVariantValue(const QVariant &variant) { return qvariant_cast(variant); } template inline QT_DEPRECATED bool qVariantCanConvert(const QVariant &variant) { return variant.template canConvert(); } #endif #endif #ifndef QT_NO_DEBUG_STREAM Q_CORE_EXPORT QDebug operator<<(QDebug, const QVariant &); Q_CORE_EXPORT QDebug operator<<(QDebug, const QVariant::Type); #endif QT_END_NAMESPACE #endif // QVARIANT_H