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
parent
e3429f764b
commit
15c13b91e6
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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>,
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
Loading…
Reference in New Issue