Add Q_IS_ENUM(), and provide as flag in QMetaType::typeFlags()

Add Q_IS_ENUM() macro to determine if a given type is an
enumeration. Use information from that in QMetaType::registerType()
to store whether custom registered metatypes are enums or not.
This information can then be accessed by calling
QMetaType::typeFlags(int type). This is used by the declarative
code to determine whether a custom type in a variant can be safely
cast to an integer, which is required to allow passing non-local
enums as signal/slot params.

Change-Id: I9733837f56af201fa3017b4a22b761437a3c0de4
Reviewed-by: Lars Knoll <lars.knoll@nokia.com>
bb10
Glenn Watson 2012-02-07 12:25:07 +10:00 committed by Qt by Nokia
parent e3429f764b
commit 15c13b91e6
6 changed files with 648 additions and 2 deletions

View File

@ -11,7 +11,9 @@ HEADERS += \
global/qnumeric.h \
global/qlogging.h \
global/qtypeinfo.h \
global/qsysinfo.h
global/qsysinfo.h \
global/qisenum.h \
global/qtypetraits.h
SOURCES += \
global/qglobal.cpp \

View File

@ -0,0 +1,64 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore/qglobal.h>
#ifndef QISENUM_H
#define QISENUM_H
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
#ifndef Q_IS_ENUM
# if defined(Q_CC_GNU) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
# define Q_IS_ENUM(x) __is_enum(x)
# elif defined(Q_CC_MSVC) && defined(_MSC_FULL_VER) && (_MSC_FULL_VER >=140050215)
# define Q_IS_ENUM(x) __is_enum(x)
# else
# include <QtCore/qtypetraits.h>
# define Q_IS_ENUM(x) QtPrivate::is_enum<x>::value
# endif
#endif
QT_END_HEADER
QT_END_NAMESPACE
#endif // QISENUM_H

View File

@ -0,0 +1,420 @@
// Copyright (c) 2006, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ----
//
// This code is compiled directly on many platforms, including client
// platforms like Windows, Mac, and embedded systems. Before making
// any changes here, make sure that you're not breaking any platforms.
//
// Define a small subset of tr1 type traits. The traits we define are:
// is_integral
// is_floating_point
// is_pointer
// is_enum
// is_reference
// is_pod
// has_trivial_constructor
// has_trivial_copy
// has_trivial_assign
// has_trivial_destructor
// remove_const
// remove_volatile
// remove_cv
// remove_reference
// add_reference
// remove_pointer
// is_same
// is_convertible
// We can add more type traits as required.
// Changes from the original implementation:
// - Move base types from template_util.h directly into this header.
// - Use Qt macros for long long type differences on Windows.
// - Enclose in QtPrivate namespace.
#ifndef QTYPETRAITS_H
#define QTYPETRAITS_H
#include <utility> // For pair
#include "QtCore/qglobal.h"
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
namespace QtPrivate {
// Types small_ and big_ are guaranteed such that sizeof(small_) <
// sizeof(big_)
typedef char small_;
struct big_ {
char dummy[2];
};
// Identity metafunction.
template <class T>
struct identity_ {
typedef T type;
};
// integral_constant, defined in tr1, is a wrapper for an integer
// value. We don't really need this generality; we could get away
// with hardcoding the integer type to bool. We use the fully
// general integer_constant for compatibility with tr1.
template<class T, T v>
struct integral_constant {
static const T value = v;
typedef T value_type;
typedef integral_constant<T, v> type;
};
template <class T, T v> const T integral_constant<T, v>::value;
// Abbreviations: true_type and false_type are structs that represent boolean
// true and false values. Also define the boost::mpl versions of those names,
// true_ and false_.
typedef integral_constant<bool, true> true_type;
typedef integral_constant<bool, false> false_type;
typedef true_type true_;
typedef false_type false_;
// if_ is a templatized conditional statement.
// if_<cond, A, B> is a compile time evaluation of cond.
// if_<>::type contains A if cond is true, B otherwise.
template<bool cond, typename A, typename B>
struct if_{
typedef A type;
};
template<typename A, typename B>
struct if_<false, A, B> {
typedef B type;
};
// type_equals_ is a template type comparator, similar to Loki IsSameType.
// type_equals_<A, B>::value is true iff "A" is the same type as "B".
//
// New code should prefer base::is_same, defined in base/type_traits.h.
// It is functionally identical, but is_same is the standard spelling.
template<typename A, typename B>
struct type_equals_ : public false_ {
};
template<typename A>
struct type_equals_<A, A> : public true_ {
};
// and_ is a template && operator.
// and_<A, B>::value evaluates "A::value && B::value".
template<typename A, typename B>
struct and_ : public integral_constant<bool, (A::value && B::value)> {
};
// or_ is a template || operator.
// or_<A, B>::value evaluates "A::value || B::value".
template<typename A, typename B>
struct or_ : public integral_constant<bool, (A::value || B::value)> {
};
template <class T> struct is_integral;
template <class T> struct is_floating_point;
template <class T> struct is_pointer;
// MSVC can't compile this correctly, and neither can gcc 3.3.5 (at least)
#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
// is_enum uses is_convertible, which is not available on MSVC.
template <class T> struct is_enum;
#endif
template <class T> struct is_reference;
template <class T> struct is_pod;
template <class T> struct has_trivial_constructor;
template <class T> struct has_trivial_copy;
template <class T> struct has_trivial_assign;
template <class T> struct has_trivial_destructor;
template <class T> struct remove_const;
template <class T> struct remove_volatile;
template <class T> struct remove_cv;
template <class T> struct remove_reference;
template <class T> struct add_reference;
template <class T> struct remove_pointer;
template <class T, class U> struct is_same;
#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
template <class From, class To> struct is_convertible;
#endif
// is_integral is false except for the built-in integer types. A
// cv-qualified type is integral if and only if the underlying type is.
template <class T> struct is_integral : false_type { };
template<> struct is_integral<bool> : true_type { };
template<> struct is_integral<char> : true_type { };
template<> struct is_integral<unsigned char> : true_type { };
template<> struct is_integral<signed char> : true_type { };
#if defined(_MSC_VER)
// wchar_t is not by default a distinct type from unsigned short in
// Microsoft C.
// See http://msdn2.microsoft.com/en-us/library/dh8che7s(VS.80).aspx
template<> struct is_integral<__wchar_t> : true_type { };
#else
template<> struct is_integral<wchar_t> : true_type { };
#endif
template<> struct is_integral<short> : true_type { };
template<> struct is_integral<unsigned short> : true_type { };
template<> struct is_integral<int> : true_type { };
template<> struct is_integral<unsigned int> : true_type { };
template<> struct is_integral<long> : true_type { };
template<> struct is_integral<unsigned long> : true_type { };
#if defined(Q_OS_WIN) && !defined(Q_CC_GNU)
template<> struct is_integral<__int64> : true_type { };
template<> struct is_integral<unsigned __int64> : true_type { };
#else
template<> struct is_integral<long long> : true_type { };
template<> struct is_integral<unsigned long long> : true_type { };
#endif
template <class T> struct is_integral<const T> : is_integral<T> { };
template <class T> struct is_integral<volatile T> : is_integral<T> { };
template <class T> struct is_integral<const volatile T> : is_integral<T> { };
// is_floating_point is false except for the built-in floating-point types.
// A cv-qualified type is integral if and only if the underlying type is.
template <class T> struct is_floating_point : false_type { };
template<> struct is_floating_point<float> : true_type { };
template<> struct is_floating_point<double> : true_type { };
template<> struct is_floating_point<long double> : true_type { };
template <class T> struct is_floating_point<const T>
: is_floating_point<T> { };
template <class T> struct is_floating_point<volatile T>
: is_floating_point<T> { };
template <class T> struct is_floating_point<const volatile T>
: is_floating_point<T> { };
// is_pointer is false except for pointer types. A cv-qualified type (e.g.
// "int* const", as opposed to "int const*") is cv-qualified if and only if
// the underlying type is.
template <class T> struct is_pointer : false_type { };
template <class T> struct is_pointer<T*> : true_type { };
template <class T> struct is_pointer<const T> : is_pointer<T> { };
template <class T> struct is_pointer<volatile T> : is_pointer<T> { };
template <class T> struct is_pointer<const volatile T> : is_pointer<T> { };
#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
namespace internal {
template <class T> struct is_class_or_union {
template <class U> static small_ tester(void (U::*)());
template <class U> static big_ tester(...);
static const bool value = sizeof(tester<T>(0)) == sizeof(small_);
};
// is_convertible chokes if the first argument is an array. That's why
// we use add_reference here.
template <bool NotUnum, class T> struct is_enum_impl
: is_convertible<typename add_reference<T>::type, int> { };
template <class T> struct is_enum_impl<true, T> : false_type { };
} // namespace internal
// Specified by TR1 [4.5.1] primary type categories.
// Implementation note:
//
// Each type is either void, integral, floating point, array, pointer,
// reference, member object pointer, member function pointer, enum,
// union or class. Out of these, only integral, floating point, reference,
// class and enum types are potentially convertible to int. Therefore,
// if a type is not a reference, integral, floating point or class and
// is convertible to int, it's a enum. Adding cv-qualification to a type
// does not change whether it's an enum.
//
// Is-convertible-to-int check is done only if all other checks pass,
// because it can't be used with some types (e.g. void or classes with
// inaccessible conversion operators).
template <class T> struct is_enum
: internal::is_enum_impl<
is_same<T, void>::value ||
is_integral<T>::value ||
is_floating_point<T>::value ||
is_reference<T>::value ||
internal::is_class_or_union<T>::value,
T> { };
template <class T> struct is_enum<const T> : is_enum<T> { };
template <class T> struct is_enum<volatile T> : is_enum<T> { };
template <class T> struct is_enum<const volatile T> : is_enum<T> { };
#endif
// is_reference is false except for reference types.
template<typename T> struct is_reference : false_type {};
template<typename T> struct is_reference<T&> : true_type {};
// We can't get is_pod right without compiler help, so fail conservatively.
// We will assume it's false except for arithmetic types, enumerations,
// pointers and cv-qualified versions thereof. Note that std::pair<T,U>
// is not a POD even if T and U are PODs.
template <class T> struct is_pod
: integral_constant<bool, (is_integral<T>::value ||
is_floating_point<T>::value ||
#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
// is_enum is not available on MSVC.
is_enum<T>::value ||
#endif
is_pointer<T>::value)> { };
template <class T> struct is_pod<const T> : is_pod<T> { };
template <class T> struct is_pod<volatile T> : is_pod<T> { };
template <class T> struct is_pod<const volatile T> : is_pod<T> { };
// We can't get has_trivial_constructor right without compiler help, so
// fail conservatively. We will assume it's false except for: (1) types
// for which is_pod is true. (2) std::pair of types with trivial
// constructors. (3) array of a type with a trivial constructor.
// (4) const versions thereof.
template <class T> struct has_trivial_constructor : is_pod<T> { };
template <class T, class U> struct has_trivial_constructor<std::pair<T, U> >
: integral_constant<bool,
(has_trivial_constructor<T>::value &&
has_trivial_constructor<U>::value)> { };
template <class A, int N> struct has_trivial_constructor<A[N]>
: has_trivial_constructor<A> { };
template <class T> struct has_trivial_constructor<const T>
: has_trivial_constructor<T> { };
// We can't get has_trivial_copy right without compiler help, so fail
// conservatively. We will assume it's false except for: (1) types
// for which is_pod is true. (2) std::pair of types with trivial copy
// constructors. (3) array of a type with a trivial copy constructor.
// (4) const versions thereof.
template <class T> struct has_trivial_copy : is_pod<T> { };
template <class T, class U> struct has_trivial_copy<std::pair<T, U> >
: integral_constant<bool,
(has_trivial_copy<T>::value &&
has_trivial_copy<U>::value)> { };
template <class A, int N> struct has_trivial_copy<A[N]>
: has_trivial_copy<A> { };
template <class T> struct has_trivial_copy<const T> : has_trivial_copy<T> { };
// We can't get has_trivial_assign right without compiler help, so fail
// conservatively. We will assume it's false except for: (1) types
// for which is_pod is true. (2) std::pair of types with trivial copy
// constructors. (3) array of a type with a trivial assign constructor.
template <class T> struct has_trivial_assign : is_pod<T> { };
template <class T, class U> struct has_trivial_assign<std::pair<T, U> >
: integral_constant<bool,
(has_trivial_assign<T>::value &&
has_trivial_assign<U>::value)> { };
template <class A, int N> struct has_trivial_assign<A[N]>
: has_trivial_assign<A> { };
// We can't get has_trivial_destructor right without compiler help, so
// fail conservatively. We will assume it's false except for: (1) types
// for which is_pod is true. (2) std::pair of types with trivial
// destructors. (3) array of a type with a trivial destructor.
// (4) const versions thereof.
template <class T> struct has_trivial_destructor : is_pod<T> { };
template <class T, class U> struct has_trivial_destructor<std::pair<T, U> >
: integral_constant<bool,
(has_trivial_destructor<T>::value &&
has_trivial_destructor<U>::value)> { };
template <class A, int N> struct has_trivial_destructor<A[N]>
: has_trivial_destructor<A> { };
template <class T> struct has_trivial_destructor<const T>
: has_trivial_destructor<T> { };
// Specified by TR1 [4.7.1]
template<typename T> struct remove_const { typedef T type; };
template<typename T> struct remove_const<T const> { typedef T type; };
template<typename T> struct remove_volatile { typedef T type; };
template<typename T> struct remove_volatile<T volatile> { typedef T type; };
template<typename T> struct remove_cv {
typedef typename remove_const<typename remove_volatile<T>::type>::type type;
};
// Specified by TR1 [4.7.2] Reference modifications.
template<typename T> struct remove_reference { typedef T type; };
template<typename T> struct remove_reference<T&> { typedef T type; };
template <typename T> struct add_reference { typedef T& type; };
template <typename T> struct add_reference<T&> { typedef T& type; };
// Specified by TR1 [4.7.4] Pointer modifications.
template<typename T> struct remove_pointer { typedef T type; };
template<typename T> struct remove_pointer<T*> { typedef T type; };
template<typename T> struct remove_pointer<T* const> { typedef T type; };
template<typename T> struct remove_pointer<T* volatile> { typedef T type; };
template<typename T> struct remove_pointer<T* const volatile> {
typedef T type; };
// Specified by TR1 [4.6] Relationships between types
template<typename T, typename U> struct is_same : public false_type { };
template<typename T> struct is_same<T, T> : public true_type { };
// Specified by TR1 [4.6] Relationships between types
#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
namespace internal {
// This class is an implementation detail for is_convertible, and you
// don't need to know how it works to use is_convertible. For those
// who care: we declare two different functions, one whose argument is
// of type To and one with a variadic argument list. We give them
// return types of different size, so we can use sizeof to trick the
// compiler into telling us which function it would have chosen if we
// had called it with an argument of type From. See Alexandrescu's
// _Modern C++ Design_ for more details on this sort of trick.
template <typename From, typename To>
struct ConvertHelper {
static small_ Test(To);
static big_ Test(...);
static From Create();
};
} // namespace internal
// Inherits from true_type if From is convertible to To, false_type otherwise.
template <typename From, typename To>
struct is_convertible
: integral_constant<bool,
sizeof(internal::ConvertHelper<From, To>::Test(
internal::ConvertHelper<From, To>::Create()))
== sizeof(small_)> {
};
#endif
}
QT_END_NAMESPACE
QT_END_HEADER
#endif // QTYPETRAITS_H

View File

@ -45,6 +45,7 @@
#include <QtCore/qglobal.h>
#include <QtCore/qatomic.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qisenum.h>
#include <new>
@ -209,7 +210,8 @@ public:
NeedsConstruction = 0x1,
NeedsDestruction = 0x2,
MovableType = 0x4,
PointerToQObject = 0x8
PointerToQObject = 0x8,
IsEnumeration = 0x10
};
Q_DECLARE_FLAGS(TypeFlags, TypeFlag)
@ -455,6 +457,8 @@ int qRegisterMetaType(const char *typeName
}
if (QtPrivate::IsPointerToTypeDerivedFromQObject<T>::Value)
flags |= QMetaType::PointerToQObject;
if (Q_IS_ENUM(T))
flags |= QMetaType::IsEnumeration;
return QMetaType::registerType(typeName, qMetaTypeDeleteHelper<T>,
qMetaTypeCreateHelper<T>,

View File

@ -41,10 +41,12 @@
#include <QtTest/QtTest>
#include <QtCore/qtypetraits.h>
class tst_QGlobal: public QObject
{
Q_OBJECT
private slots:
void qIsNull();
void for_each();
@ -53,6 +55,7 @@ private slots:
void checkptr();
void qstaticassert();
void qConstructorFunction();
void isEnum();
};
void tst_QGlobal::qIsNull()
@ -293,5 +296,124 @@ void tst_QGlobal::qConstructorFunction()
QCOMPARE(qConstructorFunctionValue, 123);
}
struct isEnum_A {
int n_;
};
enum isEnum_B_Byte { isEnum_B_Byte_x = 63 };
enum isEnum_B_Short { isEnum_B_Short_x = 1024 };
enum isEnum_B_Int { isEnum_B_Int_x = 1 << 20 };
union isEnum_C {};
class isEnum_D {
public:
operator int() const;
};
class isEnum_E {
private:
operator int() const;
};
class isEnum_F {
public:
enum AnEnum {};
};
#if defined (Q_COMPILER_CLASS_ENUM)
enum class isEnum_G : qint64 {};
#endif
void tst_QGlobal::isEnum()
{
#if defined (Q_CC_MSVC)
#define IS_ENUM_TRUE(x) (Q_IS_ENUM(x) == true)
#define IS_ENUM_FALSE(x) (Q_IS_ENUM(x) == false)
#else
#define IS_ENUM_TRUE(x) (Q_IS_ENUM(x) == true && QtPrivate::is_enum<x>::value == true)
#define IS_ENUM_FALSE(x) (Q_IS_ENUM(x) == false && QtPrivate::is_enum<x>::value == false)
#endif
QVERIFY(IS_ENUM_TRUE(isEnum_B_Byte));
QVERIFY(IS_ENUM_TRUE(const isEnum_B_Byte));
QVERIFY(IS_ENUM_TRUE(volatile isEnum_B_Byte));
QVERIFY(IS_ENUM_TRUE(const volatile isEnum_B_Byte));
QVERIFY(IS_ENUM_TRUE(isEnum_B_Short));
QVERIFY(IS_ENUM_TRUE(const isEnum_B_Short));
QVERIFY(IS_ENUM_TRUE(volatile isEnum_B_Short));
QVERIFY(IS_ENUM_TRUE(const volatile isEnum_B_Short));
QVERIFY(IS_ENUM_TRUE(isEnum_B_Int));
QVERIFY(IS_ENUM_TRUE(const isEnum_B_Int));
QVERIFY(IS_ENUM_TRUE(volatile isEnum_B_Int));
QVERIFY(IS_ENUM_TRUE(const volatile isEnum_B_Int));
QVERIFY(IS_ENUM_TRUE(isEnum_F::AnEnum));
QVERIFY(IS_ENUM_TRUE(const isEnum_F::AnEnum));
QVERIFY(IS_ENUM_TRUE(volatile isEnum_F::AnEnum));
QVERIFY(IS_ENUM_TRUE(const volatile isEnum_F::AnEnum));
QVERIFY(IS_ENUM_FALSE(void));
QVERIFY(IS_ENUM_FALSE(isEnum_B_Byte &));
QVERIFY(IS_ENUM_FALSE(isEnum_B_Byte[1]));
QVERIFY(IS_ENUM_FALSE(const isEnum_B_Byte[1]));
QVERIFY(IS_ENUM_FALSE(isEnum_B_Byte[]));
QVERIFY(IS_ENUM_FALSE(int));
QVERIFY(IS_ENUM_FALSE(float));
QVERIFY(IS_ENUM_FALSE(isEnum_A));
QVERIFY(IS_ENUM_FALSE(isEnum_A *));
QVERIFY(IS_ENUM_FALSE(const isEnum_A));
QVERIFY(IS_ENUM_FALSE(isEnum_C));
QVERIFY(IS_ENUM_FALSE(isEnum_D));
QVERIFY(IS_ENUM_FALSE(isEnum_E));
QVERIFY(IS_ENUM_FALSE(void()));
QVERIFY(IS_ENUM_FALSE(void(*)()));
QVERIFY(IS_ENUM_FALSE(int isEnum_A::*));
QVERIFY(IS_ENUM_FALSE(void (isEnum_A::*)()));
QVERIFY(IS_ENUM_FALSE(size_t));
QVERIFY(IS_ENUM_FALSE(bool));
QVERIFY(IS_ENUM_FALSE(wchar_t));
QVERIFY(IS_ENUM_FALSE(char));
QVERIFY(IS_ENUM_FALSE(unsigned char));
QVERIFY(IS_ENUM_FALSE(short));
QVERIFY(IS_ENUM_FALSE(unsigned short));
QVERIFY(IS_ENUM_FALSE(int));
QVERIFY(IS_ENUM_FALSE(unsigned int));
QVERIFY(IS_ENUM_FALSE(long));
QVERIFY(IS_ENUM_FALSE(unsigned long));
QVERIFY(IS_ENUM_FALSE(qint8));
QVERIFY(IS_ENUM_FALSE(quint8));
QVERIFY(IS_ENUM_FALSE(qint16));
QVERIFY(IS_ENUM_FALSE(quint16));
QVERIFY(IS_ENUM_FALSE(qint32));
QVERIFY(IS_ENUM_FALSE(quint32));
QVERIFY(IS_ENUM_FALSE(qint64));
QVERIFY(IS_ENUM_FALSE(quint64));
QVERIFY(IS_ENUM_FALSE(void *));
QVERIFY(IS_ENUM_FALSE(int *));
#if defined (Q_COMPILER_UNICODE_STRINGS)
QVERIFY(IS_ENUM_FALSE(char16_t));
QVERIFY(IS_ENUM_FALSE(char32_t));
#endif
#if defined (Q_COMPILER_CLASS_ENUM)
// Strongly type class enums are not handled by the
// fallback type traits implementation. Any compiler
// supported by Qt that supports C++0x class enums
// should also support the __is_enum intrinsic.
QVERIFY(Q_IS_ENUM(isEnum_G) == true);
#endif
#undef IS_ENUM_TRUE
#undef IS_ENUM_FALSE
}
QTEST_MAIN(tst_QGlobal)
#include "tst_qglobal.moc"

View File

@ -94,6 +94,7 @@ private slots:
void isRegistered();
void isRegisteredStaticLess_data();
void isRegisteredStaticLess();
void isEnum();
void registerStreamBuiltin();
void automaticTemplateRegistration();
};
@ -1042,6 +1043,39 @@ void tst_QMetaType::isRegistered()
QCOMPARE(QMetaType::isRegistered(typeId), registered);
}
enum isEnumTest_Enum0 {};
struct isEnumTest_Struct0 { enum A{}; };
enum isEnumTest_Enum1 {};
struct isEnumTest_Struct1 {};
Q_DECLARE_METATYPE(isEnumTest_Struct1)
Q_DECLARE_METATYPE(isEnumTest_Enum1)
void tst_QMetaType::isEnum()
{
int type0 = qRegisterMetaType<int>("int");
QVERIFY((QMetaType::typeFlags(type0) & QMetaType::IsEnumeration) == 0);
int type1 = qRegisterMetaType<isEnumTest_Enum0>("isEnumTest_Enum0");
QVERIFY((QMetaType::typeFlags(type1) & QMetaType::IsEnumeration) == QMetaType::IsEnumeration);
int type2 = qRegisterMetaType<isEnumTest_Struct0>("isEnumTest_Struct0");
QVERIFY((QMetaType::typeFlags(type2) & QMetaType::IsEnumeration) == 0);
int type3 = qRegisterMetaType<isEnumTest_Enum0 *>("isEnumTest_Enum0 *");
QVERIFY((QMetaType::typeFlags(type3) & QMetaType::IsEnumeration) == 0);
int type4 = qRegisterMetaType<isEnumTest_Struct0::A>("isEnumTest_Struct0::A");
QVERIFY((QMetaType::typeFlags(type4) & QMetaType::IsEnumeration) == QMetaType::IsEnumeration);
int type5 = ::qMetaTypeId<isEnumTest_Struct1>();
QVERIFY((QMetaType::typeFlags(type5) & QMetaType::IsEnumeration) == 0);
int type6 = ::qMetaTypeId<isEnumTest_Enum1>();
QVERIFY((QMetaType::typeFlags(type6) & QMetaType::IsEnumeration) == QMetaType::IsEnumeration);
}
void tst_QMetaType::isRegisteredStaticLess_data()
{
isRegistered_data();